Когда асинхронная операция выполняется в главном потоке, а когда во вторичном?
Начал разбираться с асинхронностью и вот не понимаю что происходит при выполнении асинхронных операций.
Есть асинхронный метод:
public static async Task DelayOperationAsync()
{
Operation();
Task task = Task.Delay(3000);
Operation();
await task;
Operation();
}
Метод Operation :
static void Operation()
{
Console.WriteLine("Operation ThreadID {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Begin");
Thread.Sleep(2000);
Console.WriteLine("Finish");
}
При Task.Delay(3000), 3 вызов метода Operation происходит во вторичном потоке. А если я меняю задержку например на Task.Delay(1000) то все вызовы метода Operation происходят в одном и том же потоке.
Объясните, пожалуйста, почему так.
Ответы (1 шт):
Когда вы пишете await task; вы говорите стандартному шедулеру (классу, который решает что в каком потоке выполнить) - у меня есть таск, после его выполнения мне не важно в каком потоке будет выполнено продолжение, тогда шедулер смотрит, есть ли у текущего потока контекст синхронизации (он, например, всегда есть у UI потока), если он есть, то продолжение запустится в том же потоке, где таск начался. Если контекста синхронизации нет, то шедулер запускает продолжение таска так, как считает нужным.
Если вы хотите явно выразить ваши предпочтения, то вы можете использовать ConfigureAwait, куда вы можете написать ваше предпочтение. Например,
await task.ConfigureAwait(false);
Явно укажет шедулеру, что вам не важно в каком потоке будет работать продолжение, даже если у текущего потока есть контекст синхронизации. То есть даже если таска началась в потоке с контекстом синхронизации, шедулер не будет это учитывать и запустит продолжение в любом потоке (текущем потоке или потоке из пула потоков).
Подробнее тут.