【发布时间】:2020-02-27 18:56:22
【问题描述】:
我需要隐藏 Loaded 路由事件以及启动异步任务时的某些控件。为了避免为同一事物编写两个方法,我创建了异步加载事件并为此仅调用异步任务,但我还需要更改两个 UI StatusBarItems 的内容,这不能在我的异步方法中隐藏控件。
我之前偶然发现过几次这样的例子,并认为只要您在相同的方法中调用 await,async/await 就可以让您直接更新 UI。
这样做时我总是有疑问,所以我需要澄清自己如果这是在 async/await 中做的合法事情还是非常糟糕的做法?
这是我的意思的例子:
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
//Controls on UI thread - I change their content
StatusBarItem1.Content = "Some Text";
StatusBarItem2.Content = "Test Text";
await HideControls(); //Asynchronous task
}
private async Task HideControls()
{
await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
//Hide controls in UI Thread
var All_labels = My_Grid.Children.OfType<Label>();
foreach (var item in All_Labels)
{
item.Visibility = Visibility.Hidden;
}
TextBox1.Visibility = Visibility.Hidden;
}));
}
编辑(button_click 事件):
private async void Btn_Check_Click(object sender, RoutedEventArgs e)
{
//First hide controls - if user allready cliked this button
await HideControls();
//running all tasks one at a time - Task.Delay() between them. In order to keep smoooth UI design
await Task1();
await Task2();
await Task3();
await Task4();
await Task5();
}
提前感谢您的回答!
【问题讨论】:
-
我认为您的问题没有明确的“是”或“否”答案,这在很大程度上取决于上下文。可以肯定的是,在进行 UI 修改时,您需要小心地进入 UI 线程。您的示例可能不是一个很好的示例,因为您在
Task.Delay之后没有做任何事情,所以很难看出您的方法是异步的有什么用处。您是否有更具体的示例,希望在等待后更改 UI 内容? -
@Gimly,是的,我知道这是一个简单的例子,但它是一个真实的例子。这个发布的示例只是我在 Loaded 事件上调用异步方法的一部分。另一部分是我通过 Async Button_click 执行 4 个不同的异步任务,并且能够根据需要多次运行此 Button_click,我也需要隐藏这些控件 - 在所有异步任务之前,以便将所有控件重置到同一点就像加载窗口时一样。
-
但是让你的方法在返回前等待 1 秒有什么好处呢?由于修改 UI 的代码需要在 UI 线程中,所以它在工作时无论如何都会阻塞 UI,所以 async 没有用。
-
难道不是使用 MVVM 的“正确”方式吗?无论如何,对于快速/小型程序,我和你一样脏。
-
我看不出您为
HideControls方法提供的代码是异步的。在异步方法中包含一些同步代码是绝对正常的(例如Button_Click)。不需要每行代码都以await开头。
标签: c# wpf asynchronous async-await