我正在玩一个简单的控制台应用程序,它创建一个线程,并在主线程和工作线程之间进行一些线程间通信。
我正在将对象从主线程发布到并发队列,并且工作线程正在将其出列并进行一些处理。
让我感到奇怪的是,当我分析这个应用程序时,即使我有两个内核。一个核心是 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();
}
}
}