我觉得我正在重新发明轮子。将工作分派到特定线程。我想在一个线程上顺序处理来自多个线程的事件

I feel like I'm re-inventing the wheel. Dispatch work to a specific thread. I want to process events from multiple threads sequentially on one thread

我知道 WPF 和使用 Control.Invoke 方法的表单应用程序中存在类似的东西,我也知道 BackgroundWorker、ThreadPool 等的存在

但是,我不想依赖 Forms/WPF,我想确保工作 依次 一个 线程。

编辑:理由:我想从一个线程驱动状态机。来自其他线程的事件很艰难。没有UI.

到目前为止,我无法真正弄清楚如何使用现有框架来做到这一点 类,但我可能误解了文档。

编辑:我忘了说我绑定到 .NET Framework 3.5

到目前为止我写了什么:

public class Dispatcher
{
    string Name;
    Thread WorkerThread;
    Queue<Action> WorkQueue;
    List<Exception> Exceptions;
    ManualResetEvent Gate;
    volatile bool KeepRunning;
    readonly object WorkLocker;

    public override string ToString()
    {
        return String.Format("{0}({1})", this.GetType().Name, Name);
    }

    public Dispatcher(string name)
    {
        Name = name;
        WorkLocker = new Object();
        Gate = new ManualResetEvent(false);
        WorkQueue = new Queue<Action>();
        Exceptions = new List<Exception>();
    }

    public void Start()
    {
        if (WorkerThread == null)
        {
            WorkerThread = new Thread(doDispatch)
            {
                IsBackground = true,
                Name = this.Name
            };
            WorkerThread.Start();
        }
    }

    public void Stop()
    {
        if (WorkerThread != null && WorkerThread.IsAlive)
        {
            Dispatch(() => { KeepRunning = false; });
            WorkerThread.Join();
        }
        WorkerThread = null;
    }

    public void Reset()
    {
        Stop();
        lock (WorkLocker)
        {
            WorkQueue = new Queue<Action>();
            Exceptions = new List<Exception>();
        }
    }

    public void Dispatch(Action a)
    {
        lock (WorkLocker)
        {
            WorkQueue.Enqueue(a);
        }
        Gate.Set();
    }

    public List<Exception> CollectExceptions()
    {
        List<Exception> result = new List<Exception>();
        lock(WorkLocker)
        {
            foreach(Exception e in Exceptions)
            {
                result.Add(e);
            }
            Exceptions.Clear();
        }
        return result;
    }

    private void doDispatch()
    {
        KeepRunning = true;
        while (KeepRunning)
        {
            Gate.WaitOne();
            lock (WorkLocker)
            {
                while (WorkQueue.Count > 0)
                {
                    try
                    {
                        WorkQueue.Dequeue()?.Invoke();
                    }
                    catch (Exception e)
                    {
                        Exceptions.Add(e);
                    }
                }
            }
        }
    }
}

有没有更简单的方法来做这样的事情?另一个不错的功能是能够分派具有多个参数的调用。

由于您绑定到 3.5,因此您不能使用 BlockingCollection 或 DataFlow 库...您必须自行实施。

您提供的示例代码是一个良好的开端,但您应该应用单一职责原则,以便在(如果?)升级 .NET Framework 时使其更清晰、更容易重构。

我会这样做:

  • 围绕 Queue 创建一个线程安全包装器 class 模仿 BlockingCollection,this answer provides a nice example
  • 围绕 consumer/producer 流程构建代码并注入包装器