作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在玩一个创建一个线程的简单控制台应用程序,我在主线程和工作线程之间进行一些线程间通信。
我正在将对象从主线程发布到并发队列,工作线程正在将其出列并进行一些处理。
令我感到奇怪的是,当我分析这个应用程序时,尽管我有两个内核。一个核心 100% 空闲,另一个核心完成了所有工作,我看到两个线程都在该核心中运行。
这是为什么?
是否因为我使用了一个等待句柄,它在我发布消息时设置并在处理完成时释放?
这是我的示例代码,现在使用 2 个工作线程。它的行为仍然相同,main、worker1 和 worker2 在同一个核心中运行。想法?
[编辑]它现在有点工作,至少,与昨天相比,我获得了两倍的性能。诀窍是让消费者的速度减慢到足以避免使用 AutoResetEvent 发出信号。
public class SingleThreadDispatcher
{
public long Count;
private readonly ConcurrentQueue<Action> _queue = new ConcurrentQueue<Action>();
private volatile bool _hasMoreTasks;
private volatile bool _running = true;
private int _status;
private readonly AutoResetEvent _signal = new AutoResetEvent(false);
public SingleThreadDispatcher()
{
var thread = new Thread(Run)
{
IsBackground = true,
Name = "worker" + Guid.NewGuid(),
};
thread.Start();
}
private void Run()
{
while (_running)
{
_signal.WaitOne();
do
{
_hasMoreTasks = false;
Action task;
while (_queue.TryDequeue(out task) && _running)
{
Count ++;
task();
}
//wait a short while to let _hasMoreTasks to maybe be set to true
//this avoids the roundtrip to the AutoResetEvent
//that is, if there is intense pressure on the pool, we let some new
//tasks have the chance to arrive and be processed w/o signaling
if(!_hasMoreTasks)
Thread.Sleep(5);
Interlocked.Exchange(ref _status, 0);
} while (_hasMoreTasks);
}
}
public void Schedule(Action task)
{
_hasMoreTasks = true;
_queue.Enqueue(task);
SetSignal();
}
private void SetSignal()
{
if (Interlocked.Exchange(ref _status, 1) == 0)
{
_signal.Set();
}
}
}
最佳答案
Is it because I use a wait handle that sets when I post a message and releases when the processing is done?
没有看到你的代码,很难确定,但从你的描述来看,你写的两个线程似乎充当协程:当主线程运行时,工作线程无事可做,并且反之亦然。看起来 .NET 调度程序足够聪明,不会在发生这种情况时加载第二个核心。
您可以通过多种方式更改此行为 - 例如
关于c# - 两线程一核,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21095127/
我是一名优秀的程序员,十分优秀!