Ben*_*nni 1 c# multithreading task async-await
想象一下初始化任务和两个工人:
var Init = Task.Run(async () =>
{
await Task.Delay(1000);
});
var TaskB = Task.Run(async () =>
{
await Init;
Console.WriteLine("B finished waiting");
await Task.Delay(10000000);
});
var TaskC = Task.Run(async () =>
{
await Init;
Console.WriteLine("C finished waiting");
await Task.Delay(10000000);
});
Run Code Online (Sandbox Code Playgroud)
1秒后,,TaskB
并TaskC
打印到控制台,并继续按预期.
但是,当等待Init之后首先完成的任务不使用异步方法时,其他任务await Init
调用不会完成:
var Init = Task.Run(async () =>
{
await Task.Delay(1000);
});
var TaskB = Task.Run(async () =>
{
await Init;
Console.WriteLine("B finished waiting");
await Task.Delay(5000);
});
var TaskC = Task.Run(async () =>
{
await Init;
Console.WriteLine("C finished waiting");
while (true) { }
});
Run Code Online (Sandbox Code Playgroud)
后一个示例仅向控制台打印"C finished waiting".为什么会这样?
在幕后,async/await基于任务延续构建状态机.你可以使用它来模仿它ContinueWith
和一点聪明才智(细节超出了这个答案的范围).
你需要知道的是它使用了continuation,并且默认情况下,continuation同步发生,一次一个.
在这种情况下,B和C都在创建延续Init
.这些延续将在另一个之后运行.因此,当C首先继续并进入无限循环时,它会阻止B继续.
解决方案?好吧,除了避免无限循环之外,您可以使用具有异步延续的任务.在上面执行此操作的简单方法Task.Run
如下:
var Init = Task.Run(async () =>
{
await Task.Delay(1000);
}).ContinueWith(_ => { }, TaskContinuationOptions.RunContinuationsAsynchronously);
Run Code Online (Sandbox Code Playgroud)
附录
根据OP注释,无限循环表示阻塞调用.我们可以通过不同的方法解决这种情况:
var TaskC = Task.Run(async () =>
{
await Init;
Console.WriteLine("C finished waiting");
await Task.Run(() => {while (true) { }});
});
Run Code Online (Sandbox Code Playgroud)
这样,阻塞调用不是int的延续Init
(相反,它将继续延续),因此它不会阻止其他延续Init
运行.
归档时间: |
|
查看次数: |
86 次 |
最近记录: |