Информация об изменениях

Сообщение [Этюд] - синхронный vs асинхронный от 29.09.2021 2:32

Изменено 30.09.2021 10:30 Shmj

[Этюд] - синхронный vs асинхронный
Что-то давно этюдов не было. Не знаю тянет ли это на этюд, но попробую.

Сразу код: синхронный вариант и асинхронный вариант метода (SyncMethod и AsyncMethod):

  Синхронный
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp28
{
    class Program
    {
        static void SyncMethod(int i)
        {
            Task.Delay(1).Wait(); // Много разных асинхронных вызовов обессинхрониваем - не комильфо...
            Task.Delay(1).Wait();

            // Это убрать нельзя - эмуляция вызова асинхронного метода, который мы изменить не можем.
            Thread.Sleep(1000);

            Console.WriteLine(i);
        }

        static void Main(string[] args)
        {
            for (int i = 0; i < 1000; i++)
            {
                int iCopy = i;

                // Вариант 1: синхронный метод отрабатывает быстро (для каждого вызова свой поток)
                Task.Factory.StartNew(() =>
                {
                    SyncMethod(iCopy);
                }, TaskCreationOptions.LongRunning);
            }

            Console.ReadKey();
        }
    }
}


и

  Асинхронный
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp28
{
    class Program
    {
        static async Task AsyncMethod(int i)
        {
            await Task.Delay(1); // Много разных асинхронных вызовов...
            await Task.Delay(1);

            // Это убрать нельзя - эмуляция вызова асинхронного метода, который мы изменить не можем.
            Thread.Sleep(1000);

            Console.WriteLine(i);
        }

        static void Main(string[] args)
        {
            for (int i = 0; i < 1000; i++)
            {
                int iCopy = i;

                // Вариант 2: асинхронный метод отрабатывате медленно (TaskCreationOptions.LongRunning не применяется)
                Task.Factory.StartNew(async () =>
                {
                    await AsyncMethod(iCopy);
                }, TaskCreationOptions.LongRunning);
            }


            Console.ReadKey();
        }
    }
}


Метод внутри себя имеет синхронный длительный вызов (эмулируем с помощью Thread.Sleep), который во внешней библиотеке и переписать который в асинхронном варианте мы не можем.

Итак, если запустить код — то увидим, что синхронный вариант отработает за 1-2 секунды а асинхронный — около 1 минуты (примерно, не ждал до конца). Но есть минус — в синхронном варианте внутри мы вызываем внешние асинхронные методы и каждый раз вынуждены их обессинхронивать — что не гуд.

Вопрос: как сделать, чтобы асинхронный метод отрабатывал так же быстро?
[Этюд] - синхронный vs асинхронный
Что-то давно этюдов не было. Не знаю тянет ли это на этюд, но попробую.

Сразу код: синхронный вариант и асинхронный вариант метода (SyncMethod и AsyncMethod):

  Синхронный
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp29
{
    class Program
    {
        static void SyncMethod(int i)
        {
            Task.Delay(1).Wait(); // Много разных асинхронных вызовов обессинхрониваем - не комильфо...
            Task.Delay(1).Wait();

            // Это убрать нельзя - эмуляция вызова асинхронного метода, который мы изменить не можем.
            Thread.Sleep(1000);

            Console.WriteLine(i);
        }

        static async Task Main(string[] args)
        {
            var sw = new Stopwatch();

            Console.WriteLine("Start");

            sw.Start();

            var tasks = Enumerable
                .Range(0, 1000)
                .Select(i => Task.Factory.StartNew(() => { SyncMethod(i); }, TaskCreationOptions.LongRunning));

            await Task.WhenAll(tasks);

            sw.Stop();

            Console.WriteLine("Done!");
            Console.WriteLine($"ElapsedMilliseconds={sw.ElapsedMilliseconds}");
        }
    }
}


и

  Асинхронный
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp29
{
    class Program
    {
        static async Task AsyncMethod(int i)
        {
            await Task.Delay(1); // Много разных асинхронных вызовов...
            await Task.Delay(1);

            // Это убрать нельзя - эмуляция вызова асинхронного метода, который мы изменить не можем.
            Thread.Sleep(1000);

            Console.WriteLine(i);
        }


        static async Task Main(string[] args)
        {
            var sw = new Stopwatch();

            Console.WriteLine("Start");

            sw.Start();

            var tasks = Enumerable
                .Range(0, 1000)
                .Select(AsyncMethod);

            await Task.WhenAll(tasks);

            sw.Stop();

            Console.WriteLine("Done!");
            Console.WriteLine($"ElapsedMilliseconds={sw.ElapsedMilliseconds}");
        }
    }
}


Метод внутри себя имеет синхронный длительный вызов (эмулируем с помощью Thread.Sleep), который во внешней библиотеке и переписать который в асинхронном варианте мы не можем.

Итак, если запустить код — то увидим, что синхронный вариант отработает за 1-2 секунды а асинхронный — около 1 минуты (примерно, не ждал до конца). Но есть минус — в синхронном варианте внутри мы вызываем внешние асинхронные методы и каждый раз вынуждены их обессинхронивать — что не гуд.

Вопрос: как сделать, чтобы асинхронный метод отрабатывал так же быстро?