在长时间运行的任务中显示自定义对话框窗口

时间:2015-02-10 14:32:36

标签: c# wpf async-await

假设我有一个非常简单的ProgressBar IsIndeterminate=true

<Window x:Class="My.Controls.IndeterminateProgressDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="Window"
        Width="300" Height="110" ResizeMode="NoResize" Topmost="True"
        WindowStartupLocation="CenterScreen" WindowStyle="None">

        <Grid>            
            <ProgressBar Width="200" Height="20" IsIndeterminate="True" />
        </Grid>

</Window>

我想在一个可能需要一段时间的任务期间显示此对话框。我不关心进度(我无法确定),我只是想告诉用户我做了一些可能需要几秒钟的事情。

 public void GetResult()
 {
   string result = DoWhileShowingDialogAsync().Result;
   //...
 }

 private async Task<string> DoWhileShowingDialogAsync()
 {
   var pd = new IndeterminateProgressDialog();

   pd.Show();   
   string ret = await Task.Run(() => DoSomethingComplex()));            
   pd.Close();

   return ret;
}

然而,UI只是无限地冻结,任务似乎永远不会返回。问题不在于DoSomethingComplex(),如果我同步运行它就完成没有问题。我很确定这是因为我误解了await / async的某些东西,有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:3)

.Result

这是一个经典的UI线程死锁。使用等待。在调用树中一直使用它。

答案 1 :(得分:1)

只是为了澄清一下,在呼叫树中一直使用它&#39;意味着你需要从UI线程调用它。像这样:

private Task<string> DoWhileShowingDialogAsync()
{
    return Task.Run(() => DoSomethingComplex());
} 

private string DoSomethingComplex()
{
    // wait a noticeable time
    for (int i = 0; i != 1000000000; ++i)
    ; // do nothing, just wait
}

private async void GetResult()
{
    pd.Show();
    string result = await DoWhileShowingDialogAsync();
    pd.Close();
}