class Program
{
static async Task Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
var copy = i;
_ = Task.Run(() =>
{
Console.WriteLine("Start " + copy);
Thread.Sleep(5000);
Console.WriteLine("End " + copy);
});
}
Console.ReadLine();
Console.WriteLine("Hello World!");
}
}
Одновременно запускается не так много задач — как я понял, по числу ядер процессора или типа того (на моем старичке — только 4 штуки). Где это установлено? В TaskScheduler.Current.MaximumConcurrencyLevel — офердофигища.
Здравствуйте, Shmj, Вы писали:
S>Одновременно запускается не так много задач — как я понял, по числу ядер процессора или типа того (на моем старичке — только 4 штуки). Где это установлено? В TaskScheduler.Current.MaximumConcurrencyLevel — офердофигища.
Таски тут ни при чем.
Task.Run использует для выполнения задач ThreadPool. ThreadPool, в свою очередь — это класс, который позволяет переиспользовать потоки, потому что создавать новый поток — довольно дорого.
Приложение у тебя свеженькое, в пул потоков не заполнен. Потому ThreadPool запускает обработки на нескольких потоках, остальные в очередь. И только позже, видя, что имеющихся потоков никак не хватает начинает (довольно неохотно) создавать новые.
Можешь доработать код, добавив в начало раскачку пула потоков:
for( int i = 0; i < 50; i++ )
{
var copy = i;
ThreadPool.QueueUserWorkItem( ( state ) => {
Console.WriteLine( "init pool" );
Thread.Sleep( 3000 );
} );
}
Thread.Sleep( 20000 );
а после — прошлый код и увидишь, что теперь в нем стало сразу стартовать куда больше задач.
Есть целых два древних TaskScheduler-а
Оба очень древние под древний дотнет:
int maxThreads = 2;
LimitedConcurrencyLevelTaskScheduler lcs = new LimitedConcurrencyLevelTaskScheduler(maxThreads);
QueuedTaskScheduler qs = new QueuedTaskScheduler(maxThreads);
TaskFactory factory = new TaskFactory(qs|lcs);
...
await factory.StartNew(() => ...);
QueuedTaskScheduler — этот с кучей плюшек но работает только на Windows, хотя и в .NET Core тоже. Но он и может юзать свой массив потоков и делегировать исполнение тасков заданному TaskScheduler-у.
LimitedConcurrencyLevelTaskScheduler — этот везде работает, но юзает всегда ThreadPool.
S>Одновременно запускается не так много задач — как я понял, по числу ядер процессора или типа того (на моем старичке — только 4 штуки). Где это установлено? В TaskScheduler.Current.MaximumConcurrencyLevel — офердофигища.
Здравствуйте, Shmj, Вы писали:
S>Чего й то не понял:
Ты очень не понял, если в код таски впаял Thread.Sleep(5000)
Таски как раз и придуманы чтобы переиспользовать потоки, а ты их блоканул.
Для этого дела есть
await Task.Delay(5000)
Re[2]: Task.Run - кол-во одновременных по умолчанию
Здравствуйте, fmiracle, Вы писали:
F>Task.Run использует для выполнения задач ThreadPool. ThreadPool, в свою очередь — это класс, который позволяет переиспользовать потоки, потому что создавать новый поток — довольно дорого.
Да, задать можно в ThreadPool.SetMinThreads(100, 1);
Может и дорого, но данный код выполняется быстрее во много крат, если одновременно стартануть все 100 потоков (т.к. большую часть времени просто ждет).
Re[3]: Task.Run - кол-во одновременных по умолчанию
Здравствуйте, Shmj, Вы писали:
S>Может и дорого, но данный код выполняется быстрее во много крат, если одновременно стартануть все 100 потоков (т.к. большую часть времени просто ждет).
Оптимизация тредпула не предназначена для таких задач. Для подобных задач (долгие ожидания) хороши как раз await-able таски.
Здравствуйте, Shmj, Вы писали:
S>Одновременно запускается не так много задач — как я понял, по числу ядер процессора или типа того (на моем старичке — только 4 штуки). Где это установлено? В TaskScheduler.Current.MaximumConcurrencyLevel — офердофигища.
Поскольку таски долгоживущие, запускай их соответственно:
Здравствуйте, Ночной Смотрящий, Вы писали:
S>>Может и дорого, но данный код выполняется быстрее во много крат НС>Ускорение Thread.Sleep — великое твое достижение, да.
Вопрос не этом.
Re[5]: Task.Run - кол-во одновременных по умолчанию
Здравствуйте, Shmj, Вы писали:
НС>>Ускорение Thread.Sleep — великое твое достижение, да. S>Вопрос не этом.
Вопрос именно в этом. Ты сперва блокируешь потоки, а потом прям открытие делаешь, что если блокированные потоки размножить, то работать начинает быстрее.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[6]: Task.Run - кол-во одновременных по умолчанию
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Вопрос именно в этом. Ты сперва блокируешь потоки, а потом прям открытие делаешь, что если блокированные потоки размножить, то работать начинает быстрее.
Здравствуйте, Shmj, Вы писали:
S>Одновременно запускается не так много задач — как я понял, по числу ядер процессора или типа того (на моем старичке — только 4 штуки). Где это установлено? В TaskScheduler.Current.MaximumConcurrencyLevel — офердофигища.
Значение зависит от состояния виртуальной памяти и количества ядер. Основная проблема открытия потока — это то что он минимум занимает виртуальную память под стек(насколько я помню — 2 мега). Для того чтобы программа не была подвержена DDos атакам, и всяким глупостям программистов создающим кратковременные пиковые нагрузки, сделано что новый поток открывается в ThreadPool только с некоторой задержкой, в надежде что освободится уже выполненный поток. SetMinThreads поможет, если задача реально должна потреблять столько потоков (задач).
Re[7]: Task.Run - кол-во одновременных по умолчанию
Здравствуйте, Shmj, Вы писали:
НС>>Вопрос именно в этом. Ты сперва блокируешь потоки, а потом прям открытие делаешь, что если блокированные потоки размножить, то работать начинает быстрее. S>Вопрос был: "Где это установлено?"
Тебе сразу же сказали про ThreadPool. Но я то не на то сообщение отвечал, а на вот это прекрасное заявление:
Может и дорого, но данный код выполняется быстрее во много крат, если одновременно стартануть все 100 потоков (т.к. большую часть времени просто ждет).
Т.е. ты заведомо кривой код вылечил кривым костылем, о чем я тебе и намекнул.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[8]: Task.Run - кол-во одновременных по умолчанию
НС>Может и дорого, но данный код выполняется быстрее во много крат, если одновременно стартануть все 100 потоков (т.к. большую часть времени просто ждет).
НС>Т.е. ты заведомо кривой код вылечил кривым костылем, о чем я тебе и намекнул.
Так, давай разберемся что ты хочешь донести. Что значит "кривой код"?
Да, потоки блокируем с помощью Sleep. И что? Ты вообще принципиально против блокировок потоков? Напиши свой вариант без блокировки потоков в теме: http://rsdn.org/forum/dotnet/7674190.flat
Здравствуйте, Ночной Смотрящий, Вы писали:
S>>Так, давай разберемся что ты хочешь донести. Что значит "кривой код"? НС>Ты точно программист?
Моя личность не имеет отношения к делу.
НС>И то что это в подавляющем большинстве ситуаций плохо.
Кстати, а за счет чего достигается задержка с помощью Task.Delay? Чего-то не смотрел внутренности.
>Как я тебе напишу без блокировки, если у тебя там тоже одни слипы? Запрос к серверу обычно можно делать через IOCP.
Ну, там где запрос к серверу — можно и оставить блокировку, она не на долго. А вот где ожидание — Task.Delay.
Re[11]: Task.Run - кол-во одновременных по умолчанию
Здравствуйте, Shmj, Вы писали:
S>>>Так, давай разберемся что ты хочешь донести. Что значит "кривой код"? НС>>Ты точно программист? S>Моя личность не имеет отношения к делу.
Зато имеют задаваемые тобой вопросы. Ты меня еще спроси что такое код.
НС>>И то что это в подавляющем большинстве ситуаций плохо. S>Кстати, а за счет чего достигается задержка с помощью Task.Delay? Чего-то не смотрел внутренности.
Ну так посмотри. Таймер там.
>>Как я тебе напишу без блокировки, если у тебя там тоже одни слипы? Запрос к серверу обычно можно делать через IOCP. S>Ну, там где запрос к серверу — можно и оставить блокировку, она не на долго. А вот где ожидание — Task.Delay.
Ну так вперед. Заменить свои слипы и посмотреть что вышло — быстрее чем это сообщение писать.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[12]: Task.Run - кол-во одновременных по умолчанию
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>И то что это в подавляющем большинстве ситуаций плохо. S>>Кстати, а за счет чего достигается задержка с помощью Task.Delay? Чего-то не смотрел внутренности.
НС>Ну так посмотри. Таймер там.
А таймер насколько менее ресурсоемок, нежели создание потока?
Re[13]: Task.Run - кол-во одновременных по умолчанию