Task.Factory.StartNew 保证执行顺序

alp*_*ler 3 c# multithreading task task-parallel-library

我有 2 个线程调用“Task.Factory.StartNew”。假设一个线程 (ThreadA) 比另一个线程 (ThreadB) 稍早一些。

... 在线程 A 中,稍微提前调用

Task.Run(() => {
  SomeMethodInThreadA();
});
Run Code Online (Sandbox Code Playgroud)

... 在线程 B 中,稍后调用

Task.Run(() => {
  SomeMethodInThreadB();
});
Run Code Online (Sandbox Code Playgroud)

TaskScheduler是否保证SomeMethodInThreadASomeMethodInThreadB之前先执行?

如果没有,我该怎么做?使用 Task.Factory.StartNew 并传入特殊的 TaskScheduler?

另外,除了保证先处理 SomeMethodInThreadA 之外,我还想确保SomeMethodInThreadA在执行SomeMethodInThreadB之前先完成

我研究过使用StaTaskScheduler,但我不确定这是否是解决方案。

编辑:

在没有给出关于我继承的程序的太多细节/戏剧的情况下,我想我正在寻找的是一个自定义的 TaskScheduler,它:

  1. 当委托排队时尊重序列

  2. 串行执行它们

  3. 在同一个线程中执行,类似于我上面链接的 StaTaskScheduler 源代码

Sco*_*ain 5

在没有给出关于我继承的程序的太多细节/戏剧的情况下,我想我正在寻找的是一个自定义的 TaskScheduler,它:

  1. 当委托排队时尊重序列

  2. 串行执行它们

  3. 在同一个线程中执行,类似于我上面链接的 StaTaskScheduler 源代码

如果这就是您想要的,那么您需要做的就是BlockingCollection<Action>在专用线程上循环遍历列表。

public class BackgroundJobSchedueller
{
    readonly BlockingCollection<Action> _queue;
    readonly Thread _thread;

    public BackgroundJobSchedueller()
    {
        _queue = new BlockingCollection<Action>()
        _thread = new Thread(WorkThread)
        {
            IsBackground = true,
            Name = "Background Queue Processor"
        };
        _thread.Start();
    }

    public void StopSchedueller()
    {
        //Tell GetConsumingEnumerable() to let the user out of the foreach loop
        // once the collection is empty.
        _queue.CompleteAdding();

        //Wait for the foreach loop to finish processing.
        _thread.Join();
    }

    public void QueueJob(Action job)
    {
        _queue.Add(job);
    }

    void WorkThread()
    {
        foreach(var action in _queue.GetConsumingEnumerable())
        {
            try
            {
                action();
            }
            catch
            {
                //Do something with the exception here
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当没有工作要做线程睡眠时,在 foreach 上被阻塞,一旦您将一个项目添加到队列中,它就会被处理然后重新进入睡眠状态。