gpt4 book ai didi

C#/.NET 4.5 - 为什么在 WPF 应用程序的 UI 线程中提供 Task.Delay 时 "await Task.WhenAny"永远不会返回?

转载 作者:太空狗 更新时间:2023-10-29 22:18:59 27 4
gpt4 key购买 nike

给定以下代码,为什么 ask.WhenAny 在提供 1 秒的 Task.Delay 时从不返回?从技术上讲,我不确定它是否会在很长一段时间后返回,但它不会在 15 秒左右后返回,之后我手动终止了该进程。根据文档,我不需要手动启动 delayTask,事实上,如果我尝试手动启动,我会收到一个异常。

当用户在 WPF 应用程序中选择上下文菜单项时,将从 UI 线程调用代码,但如果我为上下文菜单项指定了单击方法,则它可以正常工作在新线程中运行此代码。

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;
}

如果我将 ContextMenuItem_Click 更改为以下内容,它就可以正常工作

public void ContextMenuItem_Click(object sender, RoutedEventArgs e)
{
...
new Thread(() => SomeMethod()).Start();
...
}

最佳答案

我预测在您的调用堆栈中,您正在调用 Task.WaitTask<T>.Result .这将 cause a deadlock我在我的博客上做了完整的解释。

简而言之,发生的是 await将(默认情况下)捕获当前“上下文”并使用它来恢复其 async方法。在此示例中,“上下文”是 WPF UI 上下文。

因此,当您的代码执行其 await 时在 WhenAll 返回的任务上,它捕获 WPF UI 上下文。稍后,当该任务完成时,它将尝试在 UI 线程上恢复。但是,如果 UI 线程被阻塞(即在调用 WaitResult 时),则 async方法无法继续运行并且永远不会完成它返回的任务。

正确的解决方案是使用 await而不是 WaitResult .这意味着您的调用代码需要是 async ,它将通过您的代码库传播。最终,您需要决定如何使您的 UI 异步,这本身就是一门艺术。至少开始时,您需要一个 async void事件处理程序或某种异步 MVVM 命令(我探索 async MVVM commands in an MSDN article )。从那里你需要设计一个合适的异步用户界面;即,当异步操作正在进行时,您的 UI 的外观以及它允许​​的操作。

关于C#/.NET 4.5 - 为什么在 WPF 应用程序的 UI 线程中提供 Task.Delay 时 "await Task.WhenAny"永远不会返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23984655/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com