Продолжение задачи в streamе пользовательского интерфейса

Существует ли «стандартный» способ указать, что продолжение задачи должно выполняться в streamе, из которого была создана начальная задача?

В настоящее время у меня есть код ниже – он работает, но отслеживание диспетчера и создание второго действия кажется ненужным накладными расходами.

dispatcher = Dispatcher.CurrentDispatcher; Task task = Task.Factory.StartNew(() => { DoLongRunningWork(); }); Task UITask= task.ContinueWith(() => { dispatcher.Invoke(new Action(() => { this.TextBlock1.Text = "Complete"; } }); 

Вызовите продолжение с помощью TaskScheduler.FromCurrentSynchronizationContext() :

  Task UITask= task.ContinueWith(() => { this.TextBlock1.Text = "Complete"; }, TaskScheduler.FromCurrentSynchronizationContext()); 

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

С помощью async вы просто выполните:

 await Task.Run(() => do some stuff); // continue doing stuff on the same context as before. // while it is the default it is nice to be explicit about it with: await Task.Run(() => do some stuff).ConfigureAwait(true); 

Однако:

 await Task.Run(() => do some stuff).ConfigureAwait(false); // continue doing stuff on the same thread as the task finished on. 

Если у вас есть возвращаемое значение, которое необходимо отправить в пользовательский интерфейс, вы можете использовать общую версию следующим образом:

Это вызвано MVVM ViewModel в моем случае.

 var updateManifest = Task.Run(() => { Thread.Sleep(5000); // prove it's really working! // GenerateManifest calls service and returns 'ShippingManifest' object return GenerateManifest(); }) .ContinueWith(manifest => { // MVVM property this.ShippingManifest = manifest.Result; // or if you are not using MVVM... // txtShippingManifest.Text = manifest.Result.ToString(); System.Diagnostics.Debug.WriteLine("UI manifest updated - " + DateTime.Now); }, TaskScheduler.FromCurrentSynchronizationContext()); 

Я просто хотел добавить эту версию, потому что это такой полезный stream, и я думаю, что это очень простая реализация. Я использовал это несколько раз в различных типах, если многопоточное приложение:

  Task.Factory.StartNew(() => { DoLongRunningWork(); Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { txt.Text = "Complete"; })); }); 

J ust напишите свой код как ( Но использование ContinueWith – хорошая практика, не беспокойтесь о ненужных накладных расходах для времени выполнения )

  Task task = Task.Factory.StartNew(() => { DoLongRunningWork(); Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => { this.TextBlock1.Text = "Complete"; } }); 

Поместите код Dispatcher в блок finally если вы хотите убедиться, что это будет выполняться.

Попробуйте избежать TaskScheduler.FromCurrentSynchronizationContext() поскольку от использования этого ваш stream пользовательского интерфейса может быть заблокирован вашим текущим streamом.

  • Как заполнить сетку WPF на основе двумерного массива
  • WPF - Настройте фокус при нажатии кнопки - Без кода
  • WPF Databinding: как мне получить доступ к «родительскому» контексту данных?
  • WPF C #: переупорядочить элементы в списке с помощью перетаскивания
  • Как показать прогресс во время цикла занятости?
  • Создать редактор гитарных аккордов в WPF (из RichTextBox?)
  • Можно ли использовать другой шаблон для выбранного элемента в WPF ComboBox, чем для элементов в раскрывающемся списке?
  • WPF показывает диалог перед основным окном
  • Как точно встраиваемые свойства работают в WPF?
  • Как я могу сортировать ListBox, используя только XAML и без кода?
  • Имя не существует в ошибке пространства имен в XAML
  • Interesting Posts
    Давайте будем гением компьютера.