简体   繁体   English

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

[英]UI command *previous* to async task does not work if async task is enabled

I must not grasp async stuff as good as I thought because this has had me scratching my head for a couple of hours now.我不能像我想象的那样掌握异步的东西,因为这已经让我挠头几个小时了。

What I'm trying to accomplish is:我想要完成的是:

  1. Switch UI to "Fetching data..."将 UI 切换到“正在获取数据...”
  2. Fetch data with an async call使用异步调用获取数据
  3. Present final results based on async call基于异步调用呈现最终结果

I have the following callback from my WPF button in my view在我的视图中,我的 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;
    }

My expectations where that as soon as the user hits the button they'd see the default text of "fetching data..." due to the visibility property switch.我的期望是,一旦用户点击按钮,由于可见性属性开关,他们会看到“正在获取数据...”的默认文本。 What's happening, from what I understand, is that the program is going straight to the async task, and when it comes back it shows the success (or error) message, but it skips the "fetching data..." altogether UNLESS I comment out the code from the declaration of stockGeneratorTask down (no async call happening).据我所知,发生的事情是程序直接执行异步任务,当它返回时显示成功(或错误)消息,但它完全跳过“获取数据...”,除非我发表评论从 stockGeneratorTask 的声明中取出代码(没有发生异步调用)。

Now, if this visibility switch is happening before the async task gets triggered, shouldn't I see this change before it goes to actually make the async call?现在,如果这个可见性切换发生在异步任务被触发之前,我不应该在它实际进行异步调用之前看到这个变化吗? Why am I only seeing it after it comes back?为什么我回来后才看到?

Event handlers are the one exception that allow for async void .事件处理程序是允许async void的一个例外。 Consider making the event handler async all the way and not mixing blocking calls like .Result which could lead to deadlocks.考虑使事件处理程序一直异步,而不是混合阻塞调用,如.Result可能导致死锁。 Assuming GetStockDataAndGenerateCSV returns Task<bool> then it should be awaited.假设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;
}

Reference Async/Await - Best Practices in Asynchronous Programming参考Async/Await - 异步编程的最佳实践

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM