如果启用了异步任务,则UI命令* previous * to async task不起作用

时间:2017-12-30 00:07:41

标签: c# wpf asynchronous async-await wpf-controls

我不能抓住像我想的那样好的异步东西,因为这让我现在抓了几个小时。

我想要完成的是:

  1. 将用户界面切换为"获取数据..."
  2. 使用异步调用获取数据
  3. 根据异步调用显示最终结果
  4. 我在视图中的WPF按钮中有以下回调

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            GeneratorButton.IsEnabled = false;
            ResultMsg.Visibility = Visibility.Visible; //default text of "Fetching data..."
            string tickersString = Tickers.Text;
    
            if (!string.IsNullOrEmpty(tickersString))
            {
                tickersString = tickersString.ToUpper();
                string[] tickers = tickersString.Split(',', ' ');
    
                var stockGeneratorTask = Task.Factory.StartNew<bool>(() => GetStockDataAndGenerateCSV(tickers).Result);
    
                var allTasks = new Task[] { stockGeneratorTask };
                var tasksHandler = Task.Factory.ContinueWhenAll(allTasks, completedTasks =>
                {
                    return stockGeneratorTask.Result;
                });
    
                if (tasksHandler.Result)
                {
                    ResultMsg.Foreground = Brushes.Green;
                    ResultMsg.Text = "Your report was successfully generated.";
                }
                else
                {
                    ResultMsg.Text = "There was an error while generating your report. Please try again later.";
                    ResultMsg.Foreground = Brushes.Red;
                }
            }
    
            GeneratorButton.IsEnabled = true;
        }
    

    我的期望是,只要用户点击按钮,他们就会看到&#34;提取数据的默认文本......&#34;由于可见性属性开关。根据我的理解,正在发生的事情是程序直接进入异步任务,当它返回时它会显示成功(或错误)消息,但它会跳过提取数据。 ..&#34;除非我将stockGeneratorTask声明中的代码注释掉(没有异步调用发生)。

    现在,如果在异步任务被触发之前发生了这种可见性切换,那么在实际进行异步调用之前,我是否应该看到此更改?为什么我回来后才看到它?

1 个答案:

答案 0 :(得分:0)

事件处理程序是允许async void的一个例外。考虑使事件处理程序始终保持异步,而不是混合阻塞调用,如.Result,这可能导致死锁。假设GetStockDataAndGenerateCSV返回Task<bool>,那么应该等待它。

private async void Button_Click(object sender, RoutedEventArgs e) {
    GeneratorButton.IsEnabled = false;
    ResultMsg.Visibility = Visibility.Visible; //default text of "Fetching data..."
    var tickersString = Tickers.Text;

    if (!string.IsNullOrEmpty(tickersString)) {
        tickersString = tickersString.ToUpper();
        string[] tickers = tickersString.Split(',', ' ');
        if (await GetStockDataAndGenerateCSV(tickers)) {
            ResultMsg.Foreground = Brushes.Green;
            ResultMsg.Text = "Your report was successfully generated.";
        } else {
            ResultMsg.Foreground = Brushes.Red;
            ResultMsg.Text = "There was an error while generating your report. Please try again later.";
        }
    }

    GeneratorButton.IsEnabled = true;
}

参考Async/Await - Best Practices in Asynchronous Programming