Ответы пользователя по тегу C#
  • Как сделать асинхронность без await?

    Trixon
    @Trixon
    Суровый ASP.NET веб-разработчик
    Вы вызываете await на методе, помеченном async, назовём его MethodAsync.
    В методе MethodAsync, в точке, где вызывается другой асинхронный метод вместе с await, компилятор разбивает метод MethodAsync на две части. До await и после await.
    Всё, что было до await, выполняется в контексте первичного потока.
    Операция, помеченная await (в методе MethodAsync) + всё, что было после неё, выполняется в контексте вторичного потока.

    Вызывая await Task.Delay, Вы всё равно заимствуете вторичный поток из пула. Можно сказать, это то же самое, что вызвать await Task.Run, поместив туда часть метода, которая находилась бы после await Task.Delay.

    Вот код, пробуйте:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static async Task MethodDelayAsync()
            {
                Console.WriteLine("1. MethodDelayAsync: before await thread id: {0}", Thread.CurrentThread.ManagedThreadId);
    
                await Task.Delay(1000);
    
                Console.WriteLine("2. MethodDelayAsync: after await thread id: {0}", Thread.CurrentThread.ManagedThreadId);
            }
            
            static async Task MethodTaskRunAsync()
            {
                Console.WriteLine("1. MethodTaskRunAsync: before await thread id: {0}", Thread.CurrentThread.ManagedThreadId);
    
                await Task.Run(() =>
                {
                    Console.WriteLine("Asynchronous operation in MethodTaskRunAsync in thread id: {0}",
                        Thread.CurrentThread.ManagedThreadId);
                });
    
                Console.WriteLine("2. MethodTaskRunAsync: after await thread id: {0}", Thread.CurrentThread.ManagedThreadId);
            }
    
            static void Main(string[] args)
            {
                Console.WriteLine("Start Main in thread id: {0}", Thread.CurrentThread.ManagedThreadId);
    
                //MethodDelayAsync();
                MethodTaskRunAsync();
    
                Console.WriteLine("End Main in thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                
                Console.Read();
            }
        }
    }


    Раскомментировав MethodTaskRunAsync:
    Start Main in thread id: 1
    1. MethodTaskRunAsync: before await thread id: 1
    Asynchronous operation in MethodTaskRunAsync in thread id: 3 -- вторичный поток из пула.
    End Main in thread id: 1
    2. MethodTaskRunAsync: after await thread id: 3 -- вторичный поток из пула.

    Раскомментировав MethodDelayAsync:
    Start Main in thread id: 1
    1. MethodDelayAsync: before await thread id: 1
    End Main in thread id: 1
    2. MethodDelayAsync: after await thread id: 4 -- вторичный поток из пула.

    А это значит, что всё происходит ровно так, как сказано мною выше.
    Ответ написан