c# - 如何在 WPF 上运行异步任务而不挂 gui
问题描述
我有用于监控数据的 WPF 应用程序,我用Task.Run
Loaded 方法编写工作并在 GUI 中显示数据。
代码如下所示:
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
await Task.Run(() => DoAddAsync());
}
void DoAddAsync()
{
while (true)
{
this.Dispatcher.Invoke(() =>
{
//Do Some
});
}
}
它工作正常,我可以在不挂起的情况下更改 GUI 中的组件。
但是如果我在 中执行一个方法this.Dispatcher.Invoke
,GUI 就会挂起,在该方法关闭之前我什么也做不了。
任何人都可以帮助我在this.Dispatcher.Invoke
不挂 GUI 的情况下运行方法吗?
解决方案
您可以使用异步循环。尽管这看起来像一个无限循环,但实际上并非如此。由于延迟任务的等待,此方法会定期将控制权交还给其调用者。如果这不是具有有效异步操作的异步方法,那么它将是一个同步方法,并且会在我们调用它时使 UI 死锁。
但既然它不是,它会根据需要工作,并为您提供代码应该做什么的非常清晰的意图,并让我们一直在 UI 线程上(等待的魔力!)所以我们不有多线程问题或多个委托/回调。
private async Task DoAddAsync()
{
while (true)
{
// do the work in the loop
// ....
// don't run again for at least 200 milliseconds
await Task.Delay(200);
}
}
但是,使这项工作的真正技巧不在 DoAddAsync 方法中。它是我们如何称呼它的。您无需等待对它的调用。
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
DoAddAsync()
}
你也可以更新你的方式,但它引入了多个委托,潜在的多线程复杂性取决于正在完成的工作,我们仍然必须回到 UI 线程来更新 UI。
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
await Task.Run(async () =>
{
while (true)
{
// do the work in the loop
// update the UI on the UI thread
Dispatcher.Invoke(() => // do some );
// don't run again for at least 200 milliseconds
await Task.Delay(200);
}
});
}
推荐阅读
- python - 有什么可能的方法来缩短 Python 的 if 语句?
- javascript - 如何访问函数内声明的变量
- yii2 - Yii2 Gridview 字段显示为“(未设置)”,如果它们在数据库中出现多次
- python - 如何将 python LIST 中的项目与 DICTIONARY 键进行比较,然后使用 LIST 的所有元素构造字典
- xml - 查询控制台中的 Marklogic xdmp:log()
- javascript - 在 className 中包含特定字符串的 js querySelectorAll()
- postgresql - 过去 n 个月的 Postgres 物化视图
- hadoop - 是否有任何特定理由为 hive 中的事务表选择 ORC 文件格式?
- node.js - 当 docker 中的 js 文件中的文本发生更改时,nodemon 没有观察到
- python - Plotly:如何使用 updatemenus 更新具有多个相关跟踪的图形?