![](/img/trans.png)
[英]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.