我有用于监控数据的WPF应用程序,我在Loaded方法中编写Task.Run
来完成工作并在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就会挂起,在该方法关闭之前我无法做任何事情。
任何人都可以帮我在没有挂GUI的情况下在this.Dispatcher.Invoke
中运行方法?
您可以使用异步循环。虽然这看起来像一个无限循环,但实际上并非如此。由于等待延迟任务,此方法会定期将控制权返回给其调用者。如果这不是具有有效异步操作的异步方法,那么它将是一个同步方法,并且在我们调用它时会使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);
}
});
}