Обновить пользовательский интерфейс из задачи с действием - PullRequest
0 голосов
/ 18 марта 2020

Я хочу обновить WPF Window из Task со следующим кодом

public void DoStuff() 
{

    View.LogFenster logFenster = new View.LogFenster(logViewModel);            

    logFenster.Show();

    Action<string> loaderStatusAction = s => logViewModel.LogText += s + "\n";

    List<item> items = LoaderTask(loaderStatusAction ).Result;

}

async Task<List<item>> LoaderTask(Action<string> loaderStatusChanged )
{
        for (int i = 5; i < 90; i++)
        {
            loaderStatusChanged($"{DateTime.Now.ToString("HH:mm:ss")}: i loop");
        }

}

Но Window, связанный с logViewModel, обновляется только после завершения DoStuff и не между ними. Связывание работает, так как Window показывает 85 строк сразу после этого.

Как я могу обновлять Window каждый раз при запуске loaderStatusChanged?

1 Ответ

0 голосов
/ 18 марта 2020

Вы должны правильно использовать асинхронный метод, используя await вместо Task.Result. Task.Result вызовет асинхронный метод c синхронно в потоке пользовательского интерфейса, который заблокирует пользовательский интерфейс, поскольку у него нет свободных ресурсов для обновления макета.

public async Task DoStuff() 
{
  View.LogFenster logFenster = new View.LogFenster(logViewModel);            
  logFenster.Show();

  Action<string> loaderStatusAction = s => logViewModel.LogText += s + "\n";
  List<item> items = await LoaderTask(loaderStatusAction);    
}

Если DoStuff является обработчиком событий тогда подпись должна измениться на:

public async void DoStuff() 

Шаблон отчета о беззаботном прогрессе рекомендует использовать IProgress<T>:

public async Task DoStuff() 
{
  View.LogFenster logFenster = new View.LogFenster(logViewModel);            
  logFenster.Show();

  var progressReporter = new Progress<string>(s => logViewModel.LogText += s + "\n");
  List<item> items = await LoaderTask(progressReporter);    
}

async Task LoaderTask(IProgress<string> progressReporter)
{
  await Task.Run(
    () =>
    {
      for (int i = 5; i < 90; i++)
      {
        progressReporter.Report($"{DateTime.Now.ToString("HH:mm:ss")}: i loop");
      }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...