Mat*_*att 5 .net c# task delay
鉴于以下代码,为什么Task.WhenAny在提供1秒的Task.Delay时永远不会返回?从技术上讲,我不确定它是否会在延长的时间后返回,但是在15秒左右之后我不会手动终止该过程.根据文档,我不需要手动启动delayTask,事实上,如果我尝试手动启动,我会收到异常.
当用户选择WPF应用程序中的上下文菜单项时,将从UI线程调用代码,尽管如果我为上下文菜单项指定了click方法,则在新线程中运行此代码时,它可以正常工作.
public void ContextMenuItem_Click(object sender, RoutedEventArgs e)
{
...
SomeMethod();
...
}
public void SomeMethod()
{
...
SomeOtherMethod();
....
}
public void SomeOtherMethod()
{
...
TcpClient client = Connect().Result;
...
}
//In case you're wondering about the override below, these methods are in
//different classes i've just simplified things here a bit so I'm not posting
//pages worth of code.
public override async Task<TcpClient> Connect()
{
...
Task connectTask = tcpClient.ConnectAsync(URI.Host, URI.Port);
Task delayTask = Task.Delay(1000);
if (await Task.WhenAny(connectTask, delayTask) == connectTask)
{
Console.Write("Connected\n");
...
return tcpClient;
}
Console.Write("Timed out\n");
...
return null;
}
Run Code Online (Sandbox Code Playgroud)
如果我将ContextMenuItem_Click更改为以下它可以正常工作
public void ContextMenuItem_Click(object sender, RoutedEventArgs e)
{
...
new Thread(() => SomeMethod()).Start();
...
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*ary 12
我预测你的呼叫堆栈会更进一步,你正在呼叫Task.Wait或者Task<T>.Result.这将导致我在博客上完整解释的死锁.
简而言之,会发生的事情是await(默认情况下)捕获当前的"上下文"并使用它来恢复其async方法.在此示例中,"上下文"是WPF UI上下文.
因此,当您的代码await在返回的任务上执行时WhenAll,它会捕获WPF UI上下文.稍后,当该任务完成时,它将尝试在UI线程上继续.但是,如果UI线程被阻止(即,在调用Wait或中Result),则该async方法无法继续运行,并且永远不会完成它返回的任务.
正确的解决方案是使用await而不是Wait或Result.这意味着您的调用代码将需要async,并且它将通过您的代码库传播.最终,您需要决定如何使您的UI异步,这本身就是一门艺术.至少首先,您需要一个async void事件处理程序或某种异步MVVM命令(我在MSDN文章中探索异步MVVM命令).从那里你需要设计一个适当的异步UI; 即,当异步操作正在进行时,UI的外观以及它允许的操作.
| 归档时间: |
|
| 查看次数: |
5079 次 |
| 最近记录: |