如果启用异步任务,则UI命令 *上一个 *对异步任务不起作用



我一定不能像我想的那样掌握异步的东西,因为这使我挠头了几个小时。

我要完成的是:

  1. 将UI切换到"获取数据..."
  2. 用异步调用获取数据
  3. 根据异步调用的最终结果

我在视图中的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;
    }

我的期望在用户键入按钮后立即看到"获取数据..."的默认文本。据我了解,正在发生的事情是该程序直接执行了异步任务,而当它返回时,它显示了成功(或错误)消息,但是除非我注释,否则它会跳过"获取数据..."从stockgeneratask声明的宣言中删除代码(没有发生异步调用)。

现在,如果此可见性开关在触发异步任务之前发生了,那么在实际进行异步调用之前,我不应该看到此更改吗?为什么我只在回来后才看到它?

事件处理程序是允许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;
}

参考异步/等待 - 异步编程中的最佳实践

最新更新