Я читал о SynchronizationContext и его использовании с методами async/wait (link). По моему мнению, в приложении Console, где SynchronizationContext имеет значение null, продолжение ожидаемого метода (Task) будет запланировано с планировщиком по умолчанию, который будет ThreadPool.Продолжение задачи не было запланировано в потоке потока пула
Но если я запускаю эту консоль приложение, вы будете видеть на выходе, что продолжение выполняется на рабочем потоке, который я создал:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("MainThreadId=" + Thread.CurrentThread.ManagedThreadId);
Method1().ContinueWith(t =>
{
Console.WriteLine("After Method1. ThreadId=" + Thread.CurrentThread.ManagedThreadId);
});
Console.ReadKey();
}
public static async Task Method1()
{
Console.WriteLine("Method1 => Entered. ThreadId=" + Thread.CurrentThread.ManagedThreadId);
TaskCompletionSource<bool> completionSource = new TaskCompletionSource<bool>();
Thread thread = new Thread(() =>
{
Console.WriteLine("Method1 => Started new thread. ThreadId=" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
completionSource.SetResult(true);
});
thread.Start();
await completionSource.Task;
Console.WriteLine("Method1 => After WorkerThread. ThreadId=" + Thread.CurrentThread.ManagedThreadId);
}
}
И вот результат:
MainThreadId=10
Method1 => Entered. ThreadId=10
Method1 => Started new thread. ThreadId=11
Method1 => After WorkerThread. ThreadId=11
After Method1. ThreadId=12
Как вы можете видеть, "После WorkerThread" был выведен на тот же поток, что и мой рабочий, но не на threadpool.
Я нашел аналогичный question, но парень использовал Моно, и они говорили, что это ошибка. На моей стороне я построил этот код в Visual Studio и запустил его под Windows 7 и .Net 4.5.2, установленный на моей машине.
Не могли бы вы объяснить это поведение?
Хорошая добыча! Итак, это [статья] (http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx?PageIndex=2#comments) неверно, говоря, что «Когда ожидаемая задача завершается , продолжение будет содержать оставшуюся часть асинхронного метода.Если захваченный SynchronizationContext имеет значение NULL, то RestOfMethod() будет выполняться в исходном TaskScheduler (который часто является TaskScheduler.Default, то есть ThreadPool) "? – Absolom
@Absolom: Технически он выполняется в планировщике задач пула потоков. Нечетное поведение объясняется тем, что планировщик задач пула потоков решает, что ваш поток является частью его контекста. –
Спасибо за разъяснение, но не могли бы вы объяснить, почему в моем примере «After Method1» запланирован планировщиком задач пула потоков и фактически запущен в пуле потоков, а не в том же потоке. Почему это не похоже на поведение Async и Task? – Absolom