我在想,几乎所有使用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来完成它呢?
发布于 2014-01-29 14:29:21
您可以将中间部分拆分为帮助器异步方法:
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}将发送到关闭后具有焦点的控件,这可能导致意外操作,例如在启动消息框之前按下任何窗口上的默认按钮。如果您的目的是创建一个自动消失的弹出式窗口,但可以提前取消,那么您可能只想创建一个提供所需行为的自定义窗口。
发布于 2014-01-29 14:36:51
不完全是您的代码,但您可以这样做(未经测试):
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");我觉得很接近。
发布于 2014-01-29 14:28:43
你可以把你的任务抽象成一个方法,然后等待这个方法,比如.
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");https://stackoverflow.com/questions/21433777
复制相似问题