使用异步等待时,UI冻结

时间:2014-06-18 13:24:39

标签: c# wpf user-interface asynchronous async-await

使用异步方法让我的UI工作时遇到麻烦。这是我的代码的一部分

private async void btnDoOutput_Click(object sender, RoutedEventArgs e)
{
    /* Initiliaze */
    groupBoxConfiguration.IsEnabled = false;

    var progressIndicator = new Progress<int>();
    progressIndicator.ProgressChanged += (s,value) =>
    {
        progressExport.Value = (double)value;
        labelPercentage.Content = "Export in progress : " + value + " %";
    };
    /* do Work */

    switch (something)
    {
        case 1:
            await method(input, output, options, progressIndicator);
            break;
         default: break;
    }

    /* Finalization */  
    groupBoxConfiguration.IsEnabled = true;
}

方法是

public async static Task<string> method(string input, string output, string options, IProgress<int> progress)
{
    while(something)
    {
        //operations on input and output

        if (progress != null)
        {
            progress.Report(percentage);
        }
    }
}

当我点击我的按钮时,UI冻结,仍然启用了groupBox,直到结束才显示进度。

2 个答案:

答案 0 :(得分:1)

我认为你完全误解async / await实际上是如何运作的。您的所有代码仍然在UI线程上运行,因为您实际上并没有告诉它。这意味着await上的method毫无意义,因为无论如何它都会同步运行。

async / await的目的是允许调用代码继续处理,直到它遇到需要等待任务结果的部分代码。因此,在您的示例中,您需要更改method正文以实际返回等待Task

public Task method(string input, string output, string options, IProgress<int> progress)
{
    return Task.Run(() => {
        while(something)
        {
            //operations on input and output

           if (progress != null)
           {
               progress.Report(percentage);
           }
        }
    });
}

答案 1 :(得分:-2)

首先请不要使用静态方法,特别是静态工作者。

我相信问题是你仍然在你的UI线程上(我根据你给出的代码做了一些疯狂的假设)。尝试使用Task<string>.Factory.StartNew(...),它应该自动调用UI线程。

注意可能需要使用调度程序并调用回UI线程以使进度条工作。