Обновить
3
0
Игорь @medigor

Разработчик

Отправить сообщение
Вы в очередной раз не поняли как это все работает. Хотя по поводу блокируется ли поток ОС уже сомневаетесь))
Ещё раз с самого начала.
Асинхронная модель предполагает переиспользование потоков ОС. Как раз в местах где написано await и происходит остановка выполнения метода и этот поток может быть использован другой задачей. Соответственно когда мы дождемся результата и метод должен будет продолжить свою работу, первоначальный поток может быть занят другой задачей. Продолжение будет выполняться на любом потоке из пула потоков. Не всегда происходит остановка выполнения в месте использования await, например когда результат уже получен. Это как раз наш случай, Task.FromResult() сразу возвращает результат.
Аналогично вы пишите пургу и в других комментариях, поэтому я не буду писать ответы на все комментарии.
Это как повезет, могут и в одном, могут и в разных. А про какие именно два метода идет речь?
А ну ка, приведите код, как запускать Task.Delay() в отдельном потоке, просвятите незнающих)))
Функция getData() возвращает таск, а это значит она может выполнится в другом потоке, но для упрощения Task.Run я не писал. Если очень хочется красивый вывод можно написать что-то типа:
Func<Task<int>> getData = () =>
            {
                val++;
                var i = val;
                return Task.Run<int>(() => { Console.WriteLine($"Put : {i} : {Thread.CurrentThread.ManagedThreadId}"); return i; });
            };


В задаче было прямо сказано, не более 4 задач, на каком основании вы выполняете условие «не менее 3»

ой простите, у вас с математикой плохо? Вы оказывается школу еще не закончили? Или даже не ходили? Посмотрите еще внимательнее, счетчик начинается с 0 и обрабатываться очередь начинается когда «i >= 3». Ой простите, вы же считать не умеете, давайте перечислю все числа:
0, 1, 2, 3
неправда ли это 4?

Почему ваш воркер не начинает работать с первой задачи, а ждет, пока их станет не менее 3 в очереди?

Это вы опять ошиблись. На самом деле там запускается 4 таска, потом из очереди берется очередной из них, дожидаемся выполнения и выводим на консоль. Я изначально не хотел делать задачу с использованием каналов. Я решил задачу по другому, но суть осталась примерно та же: в очереди могут быть до 4-х задач, они запущены, но не факт что выполнены.

Если хотите на каналах, напишите сами, вот дока docs.microsoft.com/en-us/dotnet/api/system.threading.channels?view=dotnet-plat-ext-2.2

Ну или как вариант, я пишу код на c# с использованием каналов, а вы пишите код на go с использованием Task))
Я не понял, для чего запускать Task.Delay() в отдельном потоке? Я добавил эту паузу т.к. в исходном коде на go тоже была пауза 2 сек.
наконец, покажете мне код, в котором один поток складывает задачи в очередь, ограниченную по длине, а второй достает задачи из очереди и по очереди их отрабатывает?

У вас наверное память короткая, но я напомню ваши слова:
задача «собрать очередь исполнения не более 4 задач из N источников и обработать поочередно в один поток»

Собрать данные из N источников — это I/O
обработать поочередно в один поток — это CPU

Т.к. I/O это в основном ожидание, то смысла никакого нет запускать такие задачи в отдельном потоке, об этом написано в той статье, а именно когда стоит использовать Task.Run().

в каждом моменте времени выполняясь синхронно ровно в 1 поток.

Все правильно, согласно следующему условию задачи:
обработать поочередно в один поток


«10+3» — написаны через + только потому, что на месте этих чисел должны были быть переменные.

Итого: задача выполнена кратко и эффективно, полностью соответствуя условиям задачи. Про потоки вы начали писать уже после того как я выложил код. В очередной раз убеждаюсь в вашей жульнической натуре. Задним числом правила не меняют, если сам лоханулся, то признай а не придумывай отмазки.

Этот код не имеет никакого отношения к тому коду. Т.к. вы оба не понимаете как оно всё работает и думаете что блокируется поток, я сделал специально для вас этот пример.
Потому что его можно писать, а можно не писать, в разных случаях разное поведение. Я в данном случае решил не писать.
но вот этот поток, где выполнялся Main, будет выполнять Task.Delay()

Вы похоже родственники, тоже не понимаете что такое асинхронность. Ожидание не нужно выполнять, для него не нужен поток. Код выглядит как синхронный, но на самом деле строится конечный автомат и во внутренностях это выглядит как разбивка на отдельные методы, которые вызываются по очереди.

Вот вам код, скажите в каком порядке будут выведены сообщения в консоль. Если вы запустите код, то увидите не то что ожидали.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace TestSharp
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine($"Start thread: {Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(1);
            Console.WriteLine($"Continue1 thread: {Thread.CurrentThread.ManagedThreadId}");
            for (var i = 0; i < 100; i++)
            {
                var val = i;
                var x = Task.Delay(1000 + i * 10).ContinueWith((t) => Console.WriteLine($"Run: {val} Thread: {Thread.CurrentThread.ManagedThreadId}"));
            }
            Console.WriteLine($"Continue2 thread: {Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
            Console.WriteLine($"End thread: {Thread.CurrentThread.ManagedThreadId}");
        }
    }
}

пока в фоновом крутится счетчик милисекунд?

)))) Сами придумали или кто-то подсказал?
Вы же мне сейчас «откроете глаза»?

Боюсь вам никто не сможет уже открыть глаза, горбатого только могила исправит.
Thread.Sleep() блокирует поток, await Task.Delay() не блокирует.
Но вам этого никогда не понять. Говнокод ваш я тоже уже увидел. Спорить дальше не о чем.
Половину биткоина намайнил в одном потоке, а вторую спустя время во втором потоке? Это не задача, это извращение. Что это значит «генерить задачи»? Зачем генерить задачи в одном потоке, а решать в другом? Я бы решал задачу в том же потоке, в котором она генерится.
Я вот хороший пример привел с последовательным и параллельным получением данных. Go проиграл в чистую. Вы же который день не можете придумать реальную задачу.
задача «собрать очередь исполнения не более 4 задач из N источников и обработать поочередно в один поток»

Ага, так то лучше. Получается нам данные нужно получить извне ( I/O bound) и обработать в один поток (CPU bound). Тогда как-то так:
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Threading;

namespace TestSharp
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var val = 0;
            var q = new Queue<Task<int>>();

            Func<Task<int>> getData = () =>
            {
                val++;
                Console.WriteLine($"Put : {val}");
                return Task.FromResult(val);
            };

            for (var i = 0; i < 10 + 3; i++)
            {
                if (i < 10)
                    q.Enqueue(getData());

                if (i >= 3)
                {
                    await Task.Delay(2000);
                    Console.WriteLine($"Work: {await q.Dequeue()}");
                }
            }
        }
    }
}
Какую проблему решает ваш код? Да никакую. Часть вычислений выполняется в одном месте, а продолжается в другом. Я бы написал все в одном месте. Кроме как продемонстрировать использование каналов, никакого смысла в этом коде нет, использование каналов в этом примере притянуто за уши.
У нас решение задачи начинается с описания проблем. Проблему можно решить разными способами, как показывает практика, разные разработчики решают задачи разными способами. Вы же изучили новую фишку и теперь везде пытаетесь ее применить. Так поступают новички.
Да, кода от меня вы не увидите, потому что проблема, которую надо решить нет. Я в отличие от вас, попробовал написать код и на go и на c#, я попробовал использовать каналы и там и там. Я даже попробовал использовать таски, бесконечную коллекцию с помощью yield, очередь и различные комбинации этого. Конкретно в этом примере использование каналов для c# не нужно.
Зачем мне реализовывать паттерн на с# который используется в go? Это неинтересно. Интересно решить задачу, но задачи как таковой нет, вместо этого есть бесмысленный код. Я могу написать с использованием каналов, но это будет примерно такой же код. Могу написать с использованием Тасков, но он конечно получится другой, как мы будем сравнить разный код?

«чукча» просто диванный аналитик

После этих слов идешь ты в далекое путешествие, гошник упоротый
А в чем практический смысл данного кода? Как мы будем сравнивать два бесполезных кода? Если я сделаю точно такой же вывод в консоль этого будет достаточно? Подозреваю что нет.
И что с чем нужно синхронизировать? Я что то не вижу чтобы 2 потока использовали один ресурс.
И куда делся select? Вы опять пытаетесь обмануть меня? С жуликами мне нет желания общаться.
А теперь чуть-чуть усложним:

Меня ваш код не интересует. Напиши словами задачу с точки зрения пользователя. Вообще конечно писать лог можно было сразу в горутине, нафига это извращение с каналом? Ах да, кроме каналов мы ничего не знаем и не умеем. Давайте реальный код полностью, чтобы я мог его запустить у себя. Эти обрывки кода меня не интересует, потому что прежде чем выполнить select, каналы нужны инициализировать, запустить горутины, в каналы что-то писать и т.д. В итоге ваш select обрастет лапшой.

Ну и по поводу вашего «while (enable)»… Про многопоточность уже забыли? Синхронизация где? По дороге потерялась?

Совсем мозги запудрили своими каналами? Синхронизация там не нужна, т.к. цикл выполняется в одном потоке и просто добавляет в очередь задачу. А что должна делать задача нигде не сказано, может и там синхронизация не требуется.

В общем я закончил, удачи в освоении каналов, не забывайте что есть еще кучу разных технологий, но в golang о них вы можете только мечтать.
Написать-то вы можете, только каким образом оно сделает то же, что и предоставленный мной код?

А почему мой код должен делать что и ваш код? У нас задача красиво потушить сервер. Пока сервер включен, задачи добавляются в очередь с помощью Task.Run(). Когда сервер выключится цикл завершится и можно будет подождать когда выполнятся все задачи и после этого процесс завершится. Коротко и ясно! В go о таком можно только мечтать, кроме каналов ваш мозг уже не способен ничего воспринимать))

Видимо, сдаетесь?

Видимо мне пофиг, я всё выяснил что мне надо.
Я вот, например, все еще, лелею надежду, что вы прочтете текст по вашей ссылке…

Не не, вы сами еще ищите подтверждение своих фантазий, с меня хватит…

И это все…

Как это все?! Не держите нас за дураков. Каналы нужно инициализировать, читать, писать и т.д. Где весь этот код? А так я тоже могу написать:
while (enable)
{
tasks.add(Task.Run(()=>{...}));
}


В том между нами и разница: вы ассоциируете асинхронность с моделью M:1, которая наиболее распространена в C#. Я демонстрирую асинхронную модель поверх M:N.

Больше не вижу смысла с вами что-то обсуждать, подучите матчасть, тогда может быть продолжим…

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность