Эта задача в разных вариациях встречается почти на каждом собеседовании. Её цель - выяснить, насколько хорошо кандидат понимает идею асинхронности. Очень часто она является отправной точкой для обуждения, и интервьюер задает уточняющие вопросы.
Начинают с вопроса: "Что выведет код?". Далее меняют Do() на Do().Wait() или await Do().
public class Program
{
public static async Task Main(params string[] args)
{
Console.WriteLine("Hello");
Do();
Console.WriteLine("I'm Jerry");
}
public static async Task Do()
{
await Task.Delay(2000);
Console.WriteLine("World");
}
}
Этот код выведет "Hello" и "I'm Jerry". Вывод "World" не произойдет, так как в методе Main мы не ожидаем выполнения таски Do(), а внутри нее ждем 2000 миллисекунд. Это обусловлено тем, что консольное приложение завершается, когда основной поток доходит до конца метода Main. Поэтому таска Do() не будет выполнена.
При этом, если снизить время ожидания в Task.Delay до нескольких миллисекунд, то таска Do() может успеть выполниться до завершения программы и последовательность вывода "World" и "I'm Jerry" будет неопределена.
Если заменить Do() на Do().Wait(), то вывод будет следующим: "Hello", "World", "I'm Jerry". Метод Wait() ожидает выполнения таски в синхронном режиме. Это означает, что поток метода Main будет заблокирован и будет ожидать выполнения таски Do()
public class Program
{
public static async Task Main(params string[] args)
{
// Поток 1
Console.WriteLine("Hello");
// Поток 1 ждет
Do().Wait(); // Do выполняется в случайном потоке из пула
// Поток 1 продолжает выполнение
Console.WriteLine("I'm Jerry");
}
}
Если заменить Do() на await Do(), произойдет тоже самое, что и в случае с Wait(), но основной поток Main не будет ожидать выполнения таски и вернется в пул потоков. Выполнение метода продолжится в случайном потоке.
public class Program
{
public static async Task Main(params string[] args)
{
// Поток 1
Console.WriteLine("Hello");
// Поток 1 возвращается в пул потоков
await Do(); // Do выполняется в случайном потоке из пула
// Случайный поток из пула продолжает выполнение
Console.WriteLine("I'm Jerry");
}
}
Чтобы проверить вышеописанное можно запустить код в дебаге и проверить значения threadBeforeWait и threadAfterWait:
public class Program
{
public static async Task Main(params string[] args)
{
Console.WriteLine("Hello");
var threadBeforeWait = Thread.CurrentThread.ManagedThreadId;
await Do();
var threadAfterWait = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("I'm Jerry");
}
}
#техничка #csharp