Скажем, у меня есть очень простой 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;
}

Однако пользовательский интерфейс просто бесконечно зависает, и задача, похоже, никогда не возвращается. Проблема не в DoSomethingComplex (), она завершается без проблем, если я запускаю ее синхронно. Я почти уверен, что это потому, что я что-то неправильно понял с помощью await / async, может ли кто-нибудь указать мне в правильном направлении?

0
Lennart 10 Фев 2015 в 17:32

2 ответа

Лучший ответ

.Result

Это классический тупик потока пользовательского интерфейса. Используйте ожидание. Используйте его на всем пути вверх по дереву вызовов.

3
usr 10 Фев 2015 в 14:37

Просто для некоторого пояснения: «использовать его на всем пути вверх по дереву вызовов» означает, что вам нужно вызывать его из потока пользовательского интерфейса. Что-то вроде этого:

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();
}
1
DrewJordan 10 Фев 2015 в 15:35