C# 如果启用了异步任务,则异步任务的UI命令*previous*不起作用

C# 如果启用了异步任务,则异步任务的UI命令*previous*不起作用,c#,wpf,asynchronous,async-await,wpf-controls,C#,Wpf,Asynchronous,Async Await,Wpf Controls,我不能像我想的那样掌握异步的东西,因为这已经让我挠头好几个小时了 我想要实现的是: 将UI切换到获取数据。。。 使用异步调用获取数据 基于异步调用显示最终结果 在我的视图中,我有以下来自WPF按钮的回调 private void Button_Click(object sender, RoutedEventArgs e) { GeneratorButton.IsEnabled = false; ResultMsg.Visibility = Visi

我不能像我想的那样掌握异步的东西,因为这已经让我挠头好几个小时了

我想要实现的是:

将UI切换到获取数据。。。 使用异步调用获取数据 基于异步调用显示最终结果 在我的视图中,我有以下来自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;
    }
我的期望是,一旦用户点击按钮,他们就会看到获取数据的默认文本。。。由于可见性属性开关。据我所知,正在发生的事情是,程序直接进入异步任务,当它返回时,会显示成功或错误消息,但它会跳过获取数据。。。总之,除非我注释掉StockGeneratorTaskDown声明中的代码,否则不会发生异步调用


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

事件处理程序是允许异步void的一个例外。考虑始终将事件处理程序异步化,不混合阻塞调用,例如,导致死锁的结果。假设GetStockDataAndGenerateCSV返回任务,那么应该等待它

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;
}

参考资料

除非我遗漏了什么。。。您只需要将方法def更改为private async void按钮,单击,除去tickers声明和if语句之间的所有内容,并将if更改为:ifawait GetStockDataAndGenerateCSVtickers。。。。您现在访问任务的Result属性而不等待它的方式是阻塞,即不异步。您的代码都是同步的。不要使用Task.Factory.StartNew,除非您需要。