[英]Why use async and return await, when you can return Task<T> directly?
[英]What does C# “await” actually return?
下面是一些在LinqPad中“按原样”运行的代码。 它表明了我对正在await
的事情的误解。 进一步了解结果和我的问题。
void Main()
{
var cts = new CancellationTokenSource();
StartIt(cts.Token);
Thread.Sleep(500);
"Cancelling".Dump();
cts.Cancel();
}
// Define other methods and classes here
async Task StartIt(CancellationToken token)
{
"StartIt".Dump();
var o = new TestClass();
await o.Step0(token);
}
public class TestClass
{
public async Task Step0(CancellationToken token)
{
var t = Step1(token);
("Step0.Task.Id => " + t.Id).Dump();
await t;
("Step0.IsCancelled? " + t.IsCanceled).Dump();
}
public async Task Step1(CancellationToken token)
{
var t = Step2(token);
("Step1.Task.Id => " + t.Id).Dump();
try {
await t;
}
catch (OperationCanceledException)
{
"Step1.OperationCanceledException".Dump();
}
("Step1.IsCancelled? " + t.IsCanceled).Dump();
}
public Task Step2(CancellationToken token)
{
return Task.Run(() =>{
Thread.Sleep(3000);
token.ThrowIfCancellationRequested();
"Done".Dump();
}, token);
}
}
因此上面产生:
StartIt
Step1.Task.Id => 17
Step0.Task.Id => 18
Cancelling
Step1.OperationCanceledException
Step1.IsCancelled? True
Step0.IsCancelled? False
我的问题:
我希望Step0和Step1的task.Id相同。 (因此)我希望取消会传播到方法上,以便我可以询问t.IsCanceled
并采取适当的措施。
但是我得到了一个不同的Task
返回到Step0
。 我想念什么?
谢谢
我建议您阅读async
。 另外,LinqPad内置了一个出色的教程(《 C#5交互式教程》中的[示例->下载/导入更多示例->异步)。
async
代码中的任务标识符可能有些棘手。 发生的情况是,每个async Task
方法都会创建自己的任务,以表示该方法的调用。 因此, Task.Run
创建一个Task
并将其返回到Step2
和Step1
(测试中的ID 17
)。 Step1
还会创建一个Task
,并将其返回到Step0
(测试中的ID 18
)。 Step0
还创建一个Task
并将其返回给StartIt
,而StartIt
也创建一个Task
并将其返回给Main
。
所以, Task
返回的Task.Run
(这是相同的Task
由返回Step2
)被取消。 Step1
捕获已取消的异常,因此它会正常返回,并且不会取消Step1
返回的Task
。
如果要传播异常,请不要捕获已取消的异常(或者,如果您确实想捕获已记录的异常,请通过throw;
将其重新throw;
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.