c# синхронизации Как получить задачу, использующую SynchronizationContext? И как в любом случае используется SynchronizationContext?



unity synchronizationcontext (2)

Как я могу получить задачу, которая фактически запускает действие, но отправляется с помощью SynchronizationContext.Current.Send / Post?

Используйте специальный планировщик задач:

Task.Factory.StartNew(
    () => {}, // this will use current synchronization context
    CancellationToken.None, 
    TaskCreationOptions.None, 
    TaskScheduler.FromCurrentSynchronizationContext());

И может ли кто-нибудь рекомендовать хорошее введение в SynchronizationContext

Посмотрите на статью «Все о синхронности » Стивена Клири.

Я все еще изучаю всю концепцию Task и TPL. Исходя из моего понимания, функции SynchronizationContext (если они есть) используются await отправки задачи «где-то». С другой стороны, функции класса Task не используют контекст, верно?

Так, например, Task.Run(...) всегда будет отправлять действие в рабочий поток пула потоков и полностью игнорировать SynchronizationContext.Current . await Foobar() будет использовать контекст для выполнения сгенерированной задачи после await ?

Если это так, то мой вопрос: как я могу получить Task , которая фактически запускает действие, но отправляется с помощью SynchronizationContext.Current.Send/Post ?

И может ли кто-нибудь рекомендовать хорошее введение в SynchronizationContext , особенно когда и как они используются остальной частью структуры? MSDN, похоже, очень спокойно относится к классу. Лучшие хиты Google ( здесь и здесь ), похоже, предназначены только для диспетчеризации Windows Forms. Стивен Клири написал статью, в которой приятно узнать, какие контексты уже существуют и как они работают, но мне не хватает понимания того, где и когда они используются.


Когда вы это изучаете, важно указать, что Task используемый TPL, отличается от Task как используемого async / await , хотя они одинаковы. Например, TPL обычно использует родительские / дочерние задачи, но async / await этого не делает.

TPL использует планировщики задач для выполнения своих задач. Как отметил Деннис, TaskScheduler.FromCurrentSynchronizationContext предоставит вам планировщик задач, который использует Post в текущем SynchronizationContext для выполнения своей задачи.

async / await обычно не использует планировщики задач. У меня есть вступительная async / await запись в моем блоге, которая включает контекстную информацию, и я также упоминаю ее кратко в моей статье MSDN (ее легко упустить). По сути, когда async метод приостанавливается с await , по умолчанию он будет захватывать текущий SynchronizationContext (если он не равен null , и в этом случае он будет захватывать текущий TaskScheduler ). Когда метод async возобновляется, он возобновляет выполнение в этом контексте.

Деннис указал на способ TPL планирования задачи на текущий SynchronizationContext , но в мире async / await этот подход не нужен. Скорее, вы можете явно планировать задачи в пуле потоков через Task.Run :

async Task MyMethodAsync()
{
  // Whee, on a SynchronizationContext here!
  await Task.Run(() => { }); // Ooo, on the thread pool!
  // Back on the SynchronizationContext ...
  //  ... automagically!
}

Я написал статью SynchronizationContext именно потому, что документации MSDN так не хватало. У меня есть немного больше информации о моем блоге , но все важные бит находятся в статье MSDN. Многие типы используют AsyncOperation а не SynchronizationContext напрямую; лучшая документация для этого похоронена в документах EAP (раздел «Threading and Context») . Но я должен также указать, что EAP эффективно устарел из-за async / await , поэтому я не буду писать код с использованием AsyncOperation (или SynchronizationContext ) - если только я не писал собственный SynchronizationContext .





synchronizationcontext