我有2个线程调用"Task.Factory.StartNew"。假设一个线程(线程A)略微领先于另一个线程(线程B)。
。在线程 A 中,稍微提前调用
Task.Run(() => {
SomeMethodInThreadA();
});
。在线程 B 中,稍晚调用
Task.Run(() => {
SomeMethodInThreadB();
});
TaskScheduler 是否保证 SomeMethodInThreadA 在 SomeMethodInThreadB 之前先执行?
如果没有,我该怎么做?使用 Task.Factory.StartNew 并传入特殊的 TaskScheduler?
此外,除了保证首先处理 SomeMethodInThreadA 之外,我还想确保在执行 SomeMethodInThreadB 之前先完成 SomeMethodInThreadA。
我已经考虑过使用StaTaskScheduler,但我不确定这是否是解决方案。
编辑:
在不提供有关我继承的程序的太多细节/戏剧性的情况下,我想我正在寻找的是一个自定义的任务调度程序,它:
遵循委托排队时的序列
串行执行它们
在同一个线程中执行此操作,类似于我上面链接的StaTaskScheduler源代码
没有给出太多关于程序的细节/戏剧性 I 继承的,我想我正在寻找的是自定义任务调度程序 哪:
遵循委托排队时的序列
串行执行它们
在同一个线程中执行此操作,类似于我上面链接的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
}
}
}
}
当没有工作要做时,线程会休眠,在 foreach 上被阻塞,一旦您将一个项目添加到队列中,它就会被处理,然后回到睡眠状态。
TaskScheduler 是否保证 SomeMethodInThreadA 在 SomeMethodInThreadB 之前先执行?
不。
如果没有,我该怎么做?
使用"继续"让第二个任务成为第一个任务的延续
像这样:
var task = Task.Run(() => {
SomeMethodInThreadA();
});
然后后来:
task.ContinueWith(t => {
SomeOtherMethodInThreadA();
});
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => MethodA())
.ContinueWith(a =>
{
MethodB();
});
Console.WriteLine("Press a key to exit");
Console.ReadKey(false);
}
public static void MethodA()
{
Thread.Sleep(2000);
Console.WriteLine("Hello From method A {0}", Thread.CurrentThread.ManagedThreadId);
}
public static void MethodB()
{
Thread.Sleep(1000);
Console.WriteLine("Hello From method B {0}", Thread.CurrentThread.ManagedThreadId);
}
}
}
任务计划程序是否保证 SomeMethodInThreadA 得到 在 SomeMethodInThreadB 之前首先执行?
当然不是。
如果没有,我该怎么做?
如果 2 个线程彼此完全独立,但SomeMethodInThreadB
必须在SomeMethodInThreadA
完成后执行,则可以使用标准线程同步例程:
public static AutoResetEvent Wait = new AutoResetEvent(false);
然后在启动第一个任务时:
var task = Task.Run(() =>
{
// Sets the state of the event to nonsignaled, causing threads to block.
Wait.Reset();
// Execute the first task
SomeMethodInThreadA();
// The first task has finished executing -> signal the second
// thread which is probably waiting that it can start processing
// the second task
Wait.Set();
});
然后在第二个线程中等待收到第一个方法已完成执行的信号:
Task.Run(() =>
{
if (!Wait.WaitOne(TimeSpan.FromMinutes(30)))
{
// We have waited for too long the first task to execute - giving up
}
else
{
// The first task has finished executing - we can now
// proceed with the second task
SomeMethodInThreadB();
}
});
显然,由您来定义第二个线程在放弃之前等待第一个任务完成的时间。