当前位置: 首页 > 编程语言 > C#

C#-.NET4.5-为什么在WPF应用程序的UI线程中提供Task.Delay时“awaitTask.WhenAny”从不返回?

时间:2023-04-10 14:17:22 C#

C#/.NET4.5-为什么在WPF应用程序的UI线程中给定Task.Delay时“awaitTask.WhenAny”永远不会返回?给定以下代码,为什么Task.WhenAny在给定1秒的Task.Delay时永远不会返回?从技术上讲,我不确定它是否会在延长的时间后返回,但我不会在15秒左右后手动终止该进程。根据文档,我不需要手动启动delayTask,事实上,如果我尝试手动启动它,我会得到一个异常。当用户在WPF应用程序中选择上下文菜单项时,从UI线程调用代码,但如果我为上下文菜单项指定单击方法,则当我在新线程中运行此代码时,它可以正常工作。publicvoidContextMenuItem_Click(objectsender,RoutedEventArgse){...SomeMethod();...}publicvoidSomeMethod(){...SomeOtherMethod();....}publicvoidSomeOtherMethod(){...TcpClientclient=Connect().Result;...}//如果您想知道下面的重写,这些方法在//不同的类中,我只是在这里稍微简化了一些事情,所以我不会发布//有价值的代码页面。publicoverrideasyncTaskConnect(){...TaskconnectTask=tcpClient.ConnectAsync(URI.Host,URI.Port);任务delayTask=Task.Delay(1000);if(awaitTask.WhenAny(connectTask,delayTask)==connectTask){Console.Write("Connectedn");...返回tcpClient;}Console.Write("超时");...返回空;如果我将ContextMenuItem_Click更改为以下内容,它可以正常工作...}我预测您的调用堆栈更靠后,您正在调用Task.Wait或Task.Result。这将导致僵局,我在我的博客上对此进行了充分解释。简而言之,await将(默认情况下)捕获当前“上下文”并使用它来恢复其异步方法。在此示例中,“上下文”是WPFUI上下文。因此,当您的代码对WhenAll返回的任务执行WhenAll时,它会捕获WPFUI上下文。稍后,当该任务完成时,它会尝试在UI线程上继续。但是,如果UI线程被阻塞(即在对Wait或Result的调用中),则异步方法无法继续运行并且永远不会完成它返回的任务。正确的解决方案是使用await而不是Wait或Result。这意味着您的调用代码需要是异步的,并且它将通过您的代码库传播。最终,您需要决定如何使您的UI异步,这本身就是一门艺术。至少首先,您需要一个asyncvoid事件处理程序或某种异步MVVM命令(我在我的MSDN文章中探讨了异步MVVM命令)。从那里你需要设计一个合适的异步UI;即,当异步操作正在进行时,UI的外观以及它允许??的操作。以上是C#学习教程:C#/.NET4.5-为什么在WPF应用程序的UI线程中提供Task.Delay时,“awaitTask.WhenAny”从不返回?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: