Как эффективно обновить пользовательский интерфейс с помощью асинхронного метода?
Я использую 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);
}