• Как сделать асинхронность без 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 -- вторичный поток из пула.

    А это значит, что всё происходит ровно так, как сказано мною выше.
    Ответ написан
  • Как сформировать рандомную выборку товаров с присутствием минимум 1 товара определенной группы?

    Trixon
    @Trixon
    Суровый ASP.NET веб-разработчик
    Держите:

    SELECT *
    FROM public.bazaar_items
    WHERE charity IS TRUE
    UNION
    SELECT *
    FROM public.bazaar_items
    OFFSET (random()*B) LIMIT R;

    Где B -- константа, целое число, 1 <= B <= MAX - R.

    Однако я бы на Вашем месте не стал лишний раз задействовать вычислительные ресурсы сервера СУБД вызывая на нём random(), а отдал бы это на растерзание бэкенду, переписав последнюю строчку запроса как:

    OFFSET (F) LIMIT R;

    Где F -- целое число, генерирующееся в диапазоне 1 <= F <= MAX - R на бэкенде.

    MAX -- максимальное количество товаров.
    R -- максимальное количество выводимых товаров (в Вашем случае 4).

    Старайтесь держать золотую середину в составлении запроса в плане его чтения и понимания/производительности, используйте кэширование. Это и будет эффективным.
    Ответ написан