【发布时间】:2017-10-23 15:58:02
【问题描述】:
我有一个静态方法,可以从任何地方调用。在执行过程中会遇到Invoke。显然,当从 UI 线程调用此方法时,它会死锁。
这是一个再现:
public static string Test(string text)
{
return Task.Run(() =>
{
App.Current.Dispatcher.Invoke(() => { } );
return text + text;
}).Result;
}
void Button_Click(object sender, RoutedEventArgs e) => Test();
我已经阅读了多个问题,并且喜欢 @StephenCleary 的 10 个答案(甚至一些博客链接自这些),但我不明白如何实现以下目标:
- 有一个静态方法,易于调用并从任何地方(例如 UI 事件处理程序、任务)获取结果;
- 此方法应阻止调用方,之后调用方代码应继续在同一上下文中运行;
- 此方法不应冻结 UI。
与Test() 的行为最接近的类比是MessageBox.Show()。
它可以实现吗?
P.S.:为了简短起见,我没有附上我的各种 async/await 尝试以及用于 UI 调用的尝试,但使用 DoEvents 的尝试看起来很糟糕。
【问题讨论】:
-
@PoweredByOrange 访问
.Result属性是阻塞调用。 -
删除
.Result并设置返回类型Task<string>然后你的调用代码可以await结果。这将导致调用代码暂停,然后在获得结果后继续。这符合要求吗? -
如果在 UI 线程内调用,您的代码将阻塞 UI。如果要释放 UI 线程,您有两种选择:
async事件处理程序或BackgroundWorker。 -
@FedericoDipuma BGW 已过时,根本不需要事件处理程序。使用 .NET 4.5+ 中的
IProgress< T>类执行进度报告。或者只是分解 UI 中的方法和真正的异步部分并使用await等待异步部分的执行 -
@Sinatr 你想做什么?您为什么要尝试从任务内部修改 UI?为什么不使用异步事件处理程序?
标签: c# wpf multithreading async-await