C# 6 等待任务和所有子任务的完全完成
C# 6 waiting for full completion of task and all subtasks
我正在尝试构建一种调度程序(这可能不是相关术语),它将 运行 按顺序执行多个任务。
这是我的POC代码(请忽略queue/dequeue机制,它很差,但我猜不是这里的问题)
编辑:感谢 @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<Func<Task>>
而不是 ProcessingQueue<Action>
public class ProcessingQueue
{
Queue<Func<Task>> _Queue = new Queue<Func<Task>>();
private bool _stillRunning = false;
public void Enqueue(Func<Task> a)
{
lock (_Queue)
{
_Queue.Enqueue(a);
if (_stillRunning == false)
{
StartProcessing();
}
}
}
private void StartProcessing()
{
_stillRunning = true;
Task.Run(async () =>
{
Func<Task> a = null;
while (true)
{
lock (_Queue)
{
if (_Queue.Any() == true)
{
a = _Queue.Dequeue();
}
else
{
break;
}
}
await a(); //how to wait for all subtasks!!???
}
_stillRunning = false;
});
}
说明
在有问题的代码中,
Action a;
...
await Task.Run(a);
您正在执行 Task.Run(Action action)
,因为操作可能包含异步任务,Run
方法不会等待任务,因为没有任务。当您调用 Task.Run(Func<Task> task)
Run
方法时,知道它是任务并且会等待它,
我正在尝试构建一种调度程序(这可能不是相关术语),它将 运行 按顺序执行多个任务。
这是我的POC代码(请忽略queue/dequeue机制,它很差,但我猜不是这里的问题)
编辑:感谢 @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<Func<Task>>
而不是 ProcessingQueue<Action>
public class ProcessingQueue
{
Queue<Func<Task>> _Queue = new Queue<Func<Task>>();
private bool _stillRunning = false;
public void Enqueue(Func<Task> a)
{
lock (_Queue)
{
_Queue.Enqueue(a);
if (_stillRunning == false)
{
StartProcessing();
}
}
}
private void StartProcessing()
{
_stillRunning = true;
Task.Run(async () =>
{
Func<Task> a = null;
while (true)
{
lock (_Queue)
{
if (_Queue.Any() == true)
{
a = _Queue.Dequeue();
}
else
{
break;
}
}
await a(); //how to wait for all subtasks!!???
}
_stillRunning = false;
});
}
说明
在有问题的代码中,
Action a;
...
await Task.Run(a);
您正在执行 Task.Run(Action action)
,因为操作可能包含异步任务,Run
方法不会等待任务,因为没有任务。当您调用 Task.Run(Func<Task> task)
Run
方法时,知道它是任务并且会等待它,