Всем привет. Сейчас изучаю асинхронность в C# и решил проверить цепочки вызовов await.
Я много раз читал, что если await встречает Таск, который ещё не выполнен, то метод возвращает незавершённый таск и выполнение продолжается в вызывающем методе.
Почему после строки
await Method2Async() в первом примере управление не передаётся в Main, а начинает выполняться Method2Async в том же потоке?
А во втором примере, когда вместо
await Method2Async() написать
await Task.Run(Method2Async), наоборот. В итоге будет разный вывод. Был бы рад, если кто-нибудь расскажет больше о том, как работают такие цепочки или скинул какой-нибудь источник. Заранее спасибо за ответ.
1:
static void Main(string[] args)
{
Console.WriteLine("MAIN BEFORE Method1Async THREAD ID : " + Thread.CurrentThread.ManagedThreadId);
Task method1Task = Method1Async();
Console.WriteLine("MAIN AFTER Method1Async THREAD ID : " + Thread.CurrentThread.ManagedThreadId);
Console.Read();
}
static async Task Method1Async()
{
Console.WriteLine("Starting Method1Async Thread id: "+ Thread.CurrentThread.ManagedThreadId);
await Method2Async(); // Меняется только эта строка
Console.WriteLine("End Method1Async Thread id: " + Thread.CurrentThread.ManagedThreadId);
}
static async Task Method2Async()
{
Thread.Sleep(100);
Console.WriteLine("Starting Method2Async Thread id: "+ Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
Thread.Sleep(100);
Console.WriteLine("INNER TASK STARTED Thread id: " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
Console.WriteLine("INNER TASK ENDED Thread id: " + Thread.CurrentThread.ManagedThreadId);
});;
Console.WriteLine("End Method2Async Thread id: " + Thread.CurrentThread.ManagedThreadId);
}
Вывод:
MAIN BEFORE Method1Async THREAD ID : 1
Starting Method1Async Thread id: 1
Starting Method2Async Thread id: 1
MAIN AFTER Method1Async THREAD ID : 1
INNER TASK STARTED Thread id: 5
INNER TASK ENDED Thread id: 5
End Method2Async Thread id: 5
End Method1Async Thread id: 5
2:
static void Main(string[] args)
{
Console.WriteLine("MAIN BEFORE Method1Async THREAD ID : " + Thread.CurrentThread.ManagedThreadId);
Task method1Task = Method1Async();
Console.WriteLine("MAIN AFTER Method1Async THREAD ID : " + Thread.CurrentThread.ManagedThreadId);
Console.Read();
}
static async Task Method1Async()
{
Console.WriteLine("Starting Method1Async Thread id: "+ Thread.CurrentThread.ManagedThreadId);
await Task.Run(Method2Async); // Меняется только эта строка
Console.WriteLine("End Method1Async Thread id: " + Thread.CurrentThread.ManagedThreadId);
}
static async Task Method2Async()
{
Thread.Sleep(100);
Console.WriteLine("Starting Method2Async Thread id: "+ Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
Thread.Sleep(100);
Console.WriteLine("INNER TASK STARTED Thread id: " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
Console.WriteLine("INNER TASK ENDED Thread id: " + Thread.CurrentThread.ManagedThreadId);
});;
Console.WriteLine("End Method2Async Thread id: " + Thread.CurrentThread.ManagedThreadId);
}
Вывод:
MAIN BEFORE Method1Async THREAD ID : 1
Starting Method1Async Thread id: 1
MAIN AFTER Method1Async THREAD ID : 1
Starting Method2Async Thread id: 4
INNER TASK STARTED Thread id: 7
INNER TASK ENDED Thread id: 7
End Method2Async Thread id: 7
End Method1Async Thread id: 7