Я хочу обновления статуса из долгого метода. Обычно я использую диспетчер, чтобы отправить обратно в поток пользовательского интерфейса, но мне интересно, как использовать async.async WPF несколько обновлений статуса в потоке пользовательского интерфейса
Для простоты:
Создать окно, добавьте кнопку
<Button Name="ButtonWithCodeBehind" Height="25" Click="ButtonWithCodeBehindOnClick"/>
добавить некоторый код позади обработчика OnClick
private async void ButtonWithCodeBehindOnClick(object sender, RoutedEventArgs e)
{
await Task.Factory.StartNew(() =>
{
ButtonWithCodeBehind.Content = "First";
Thread.Sleep(1000);
ButtonWithCodeBehind.Content = "Second";
Thread.Sleep(1000);
ButtonWithCodeBehind.Content = "Third";
});
}
Это, очевидно, будет перерыв, потому что ButtonWithCodeBehind.Content будет доступ к неправильной теме.
Есть ли способ, чтобы сделать эту работу, не делая что-то вроде:
Deployment.Current.Dispatcher.BeginInvoke(()=>ButtonWithCodeBehind.Content = "Second");
Критическим моментом здесь является длинный ход задача будет генерировать обновления, как она прогрессирует, я могу реорганизовать код что-то вроде этого :
private async void ButtonWithCodeBehindOnClick(object sender, RoutedEventArgs e)
{
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
await Task.Factory.StartNew(() =>
{
Task.Factory.StartNew(() => Thread.Sleep(1000))
.ContinueWith(t => ButtonWithCodeBehind.Content = "First", scheduler)
.ContinueWith(t => Thread.Sleep(1000))
.ContinueWith(t => ButtonWithCodeBehind.Content = "Second", scheduler)
.ContinueWith(t => Thread.Sleep(1000))
.ContinueWith(t => ButtonWithCodeBehind.Content = "Third", scheduler);
});
}
Но это изящно. Кроме того, если вы вытащили асинхронные и ожидали ключевые слова и заменили их на Task.WaitAll, он все равно выполнил бы, как ожидалось.
Примечание: Если вам интересно, почему я использую Thread.Sleep вместо Task.Delay, я на самом деле тестирую это в Silverlight, а поддержка async-ожидания не включает .Delay (или по крайней мере не там, где я ожидаю, что это будет).
для имитации работы Task.Run + Thread.Sleep в порядке. для «ожидания немного» Task.Delay - это способ пойти, хотя – Dbl
Спасибо Андреасу, Thread.Sleep был потому, что я использовал Silverlight в то время, а Silverlight не включает Task.Delay :( – Ian