Как эффективно обновить пользовательский интерфейс с помощью асинхронного метода?

Я использую ProgressBar с привязкой, чтобы показать прогресс при получении файла с удаленного устройства.

<ProgressBar Width="500" Height="50" Value="{Binding ProgressFileReceive}"/>

ProgressFileReceive это свойство (double) в моей модели просмотра, которая имеет процент завершения. Поэтому для обновления индикатора выполнения я добавляю к этому номеру.

Проблема у меня есть метод передачи файлов в другом async метод и так, чтобы получить доступ к этому свойству, я должен использовать следующий код:

await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
   () =>
   {
       // do something on the UI thread
       ProgressFileReceive = (double)i / fileSize * 100;
   });

Это работает, но делает весь процесс чрезвычайно медленным, поскольку на каждой итерации (с тех пор, как я читаю побайтно, существует более тысячи циклов), метод должен использовать диспетчер для обновления пользовательского интерфейса. Получение целого файла занимает в несколько раз больше времени, чем если бы я не обновлял пользовательский интерфейс.

Как я могу сделать это более эффективно, чтобы ускорить процесс?

1 ответ

Проблема в том, что у меня есть метод передачи файлов в другом асинхронном методе

Это не обязательно следует. Вам не нужно использовать CoreDispatcher в явном виде. Асинхронные методы возобновляются в потоке пользовательского интерфейса по умолчанию.


Для отчетов о прогрессе, вы должны использовать IProgress<T>, Вы можете использовать его со структурой для отчета о прогрессе, как таковой:

public struct ProgressReport
{
  public double Progress { get; set; }
  public double FileSize { get; set; }
}

async Task FileTransferAsync(IProgress<ProgressReport> progress)
{
  ...
  if (progress != null)
  {
    progress.Report(new ProgressReport
    {
      Progress = (double)i,
      FileSize = fileSize
    });
  }
  ...
}

Тогда вы можете потреблять его с IProgress<T> реализация. Так как вам нужно регулирование пользовательского интерфейса, вы можете использовать тот, который я написал, который имеет встроенное регулирование:

using (var progress = ObservableProgress<ProgressReport>.CreateForUi(value =>
    {
        ProgressFileReceive = (double)value.Progress / value.FileSize * 100;
    }))
{
    await FileTransferAsync(progress);
}
Другие вопросы по тегам