我正在尝试构建一种可以按顺序运行若干任务的调度程序(这可能不是相关术语)。C#6正在等待完成任务和所有子任务
这里是我的POC代码(请忽略队列/出列机制较差,但不是这里的问题,我猜)
编辑:感谢的@Theraot
static void Main(string[] args)
{
ProcessingQueue o_q = new ProcessingQueue();
o_q.Enqueue(async() => { await SimulateTaskSequence(1); });
o_q.Enqueue(async() => { await SimulateTaskSequence(2); });
Console.ReadLine();
}
public static async Task SimulateTaskSequence(int taskNbr)
{
Console.WriteLine("T{0} - Working 1sec", taskNbr);
Thread.Sleep(1000);
Console.WriteLine("T{0} - Zzz 1st 1sec", taskNbr);
await Task.Delay(1000);
Console.WriteLine("T{0} - Working 1sec", taskNbr);
Thread.Sleep(1000);
Console.WriteLine("T{0} - Done", taskNbr);
}
public class ProcessingQueue
{
Queue<Action> _Queue = new Queue<Action>();
private bool _stillRunning = false;
public void Enqueue(Action a)
{
lock (_Queue)
{
_Queue.Enqueue(a);
if (_stillRunning == false)
{
StartProcessing();
}
}
}
private void StartProcessing()
{
_stillRunning = true;
Task.Run(async() =>
{
Action a = null;
while (true)
{
lock (_Queue)
{
if (_Queue.Any() == true)
{
a = _Queue.Dequeue();
}
else
{
break;
}
}
await Task.Run(a); //how to wait for all subtasks!!???
}
_stillRunning = false;
});
}
我的问题的帮助一旦第一个任务(T1)的第一个等待发生,第二个任务(T2)开始执行。
我得到以下输出:
T1 - Working 1sec
T1 - Zzz 1st 1sec
T2 - Working 1sec
T2 - Zzz 1st 1sec
T1 - Working 1sec
T1 - Done
T2 - Working 1sec
T2 - Done
但是我期待是:
T1 - Working 1sec
T1 - Zzz 1st 1sec
T1 - Working 1sec
T1 - Done
T2 - Working 1sec
T2 - Zzz 1st 1sec
T2 - Working 1sec
T2 - Done
我明白为什么这是默认的行为,但我需要改变。我在一个新的TaskFactory中玩耍TaskContinuationOptions和TaskCreationOptions,但没有更好的结果。 这甚至可能吗?
非常感谢 克里斯托夫
您的ProcessingQueue类已经存在于框架中,它是ThreadPool。很难正确替换,并且它不会执行ThreadPool不做的任何操作。除了等待和即时出错。不要这样做。 –
@HansPassant OP所需要的与ThreadPool不同,OP需要添加的任务按顺序完成。在ThreadPool中,你没有这样的保证,实际上ThreadPool的想法是使用多个线程并行运行(编辑:并重用线程)。现在,可以通过同步运行这些任务来实现,或者通过使用Thread来等待的其他方式来实现... OP不需要任何这些任务。 – Theraot
Task类组合得非常好,他所需要的只是ContinueWith对主任务和WaitAll进行排序,以等待子任务完成。简单易用,但是当你发明自己的线程池时很难看清楚。 –