Почему Task начинает работу только после запуска всего List<Task>?

Рейтинг: 0Ответов: 1Опубликовано: 13.04.2023

Сабж. Помогите разобраться в этой магии.
Есть такой класс.

public class ParserV2 
{
    private static SemaphoreSlim semaphore = new SemaphoreSlim(3);
    private static  HttpClient client = new HttpClient();

    private Domain domain;

    static ParserV2()
    {
     //Устанавливаем Заголовки
    }
    private async Task GetDomainAsync(){//Делаем GET запрос к апи}
    private async Task CheckDomainAsync(){//Делаем проверку}
    private async Task<string> UpdateBdDomainAsync(){//Делаем PUT запрос к апи}
       //Метод которым запускаем все действия которые выше    
    public async Task Check(CancellationToken token) 
    {
        if (!token.IsCancellationRequested)
        {
            
            semaphore.Wait();
           
        do
        {     
                await GetDomainAsync();         
        }
        while (domain == null);

        do
        {
            await CheckDomainAsync();
        }
        while (domain.CMS == null);


        while(true) 
        {
            var code = await UpdateBdDomainAsync();
            if (code =="OK") 
            {
                break;      
            }
        }
        Console.WriteLine("Поток освобожден");
        semaphore.Release();
        }
    }
}
    

Main у меня такой

CancellationTokenSource cts = new CancellationTokenSource();
List <ParserV2> parse = new List <ParserV2> ();

for (int i = 0; i < 20; i++) 
{
  parse.Add(new ParserV2());
}

List <Task> tasksParse = new List <Task> ();

foreach(var t in parse) 
{
  tasksParse.Add(new Task(() => t.Check(cts.Token)));
}

foreach (var t in tasksParse)
{
 t.Start();
}

Проблема в том что задачи начинают выполнятся только после того как в foreach всем сделает t.Start();
Я думал что таски которые я запускаю сразу будут выполнятся но это не так.
Как мне запускать таски по мере их запуска а не все сразу?

Ответы

▲ 1Принят

Ошибка: semaphore.Wait(); замените на await semaphore.WaitAsync(); и все заработает как надо.

Не используйте конструктор new Task, вообще никогда, используйте Task.Run, тогда таски будут стартовать сразу. tasksParse.Add(Task.Run(() => t.Check(cts.Token))); - а второй цикл со .Start() не нужен.

Хотя, это же асинхронный метод, ему вообще не нужен Task.Run. Вот так надо.

tasksParse.Add(t.Check(cts.Token));

Вот ещё интересное, поразбирайтесь: Массовые асинхронные вызовы с ограничением на количество параллельных без семафора