[英]Understanding async/await vs Wait in C# with “ContinueWith” behavior
[英]async/await vs ContinueWith
我在想,幾乎所有使用ContinueWith
代碼都可以用async/await
重構,但這個代碼有點難。 我要轉換的草圖:
// UI unit testing: close the message box in 1s
Task.Delay(1000).ContinueWith((t) =>
{
SendKeys.Send("{ENTER}");
}, TaskScheduler.FromCurrentSynchronizationContext());
MessageBox.Show("Hello!");
Debug.Print("continue after a message box");
如何使用async/await
?
您可以將中間部分拆分為輔助異步方法:
private async Task EnterAfterDelay()
{
await Task.Delay(1000);
SendKeys.Send("{ENTER}");
}
private void MyMethod()
{
EnterAfterDelay();
MessageBox.Show("Hello!");
Debug.Print("continue after a message box");
}
這揭示了原始代碼的問題,即繼續任務永遠不會被“等待”(在原始上下文中給出一個ContinueWith),這意味着它拋出的任何異常都將是未處理的。 理想情況下,你將它存儲在某個地方的Task變量中,並決定一個好的地方等待它並處理它拋出的任何異常。
一個簡短的說明:
無論使用哪種方法,如果用戶在第二個過去之前關閉消息框,{ENTER}將被發送到關閉后具有焦點的任何控件,這可能導致意外的操作,例如在任何活動的窗口上按下默認按鈕在啟動消息框之前。 如果打算創建一個自動消失但可以提前解散的彈出窗口,您可能只想創建一個提供所需行為的自定義窗口。
不完全是你的代碼,但你可以做這樣的事情(未經測試):
Func<Action, Task> doAsync = async (action) =>
{
await Task.Yield();
action();
};
var messageBoxTask = doAsync(() =>
MessageBox.Show("Hello!"));
var delay = Task.Delay(1000);
var task = await Task.WhenAny(delay, messageBoxTask);
if (task != messageBoxTask)
{
SendKeys.Send("{ENTER}")
await messageBoxTask;
}
Debug.Print("continue after a message box");
我認為它非常接近。
您可以將任務抽象為方法,然后等待方法,如...
Task DelayTask() {
return Task.Delay(1000);
}
await DelayTask();
SendKeys.Send("{ENTER}");
MessageBox.Show("Hello!");
Debug.Print("continue after a message box");
或者你可以像...那樣寫它
await Task.Delay(1000);
SendKeys.Send("{ENTER}");
MessageBox.Show("Hello!");
Debug.Print("continue after a message box");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.