两个线程一个核心

Rog*_*son 8 c# multithreading autoresetevent

我正在玩一个简单的控制台应用程序,它创建一个线程,我在主线程和工作线程之间进行一些线程间的通信.

我将主线程中的对象发布到并发队列,而工作线程将该队列出列并进行一些处理.

令我感到奇怪的是,当我描述这个应用程序时,即使我有两个核心.一个核心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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

das*_*ght 7

是因为我在发布消息时使用等待句柄,在处理完成后释放吗?

在没有看到代码的情况下,很难确定,但是根据您的描述,您编写的两个线程似乎充当了协同例程:当主线程运行时,工作线程无关,反之亦然.看起来.NET调度程序非常智能,在发生这种情况时不会加载第二个核心.

您可以通过多种方式更改此行为 - 例如

  • 通过在等待句柄之前在主线程上做一些工作,或者
  • 通过添加更多工作线程来竞争主线程发布的任务,并且可以同时完成任务.