Задача.Сбой Factory.StartNew() при очень быстром запуске двух задач

#c# #task-parallel-library

#c# #task-parallel-library

Вопрос:

При одновременном запуске двух задач (или почти одновременно) с задачей.Factory.StartNew(), одна из них всегда завершается немедленно.

У меня есть функция, которая создает задачу из основного потока, которая затем сама запускает некоторое количество задач в зависимости от количества параллельных заданий, которые необходимо выполнить. Более конкретно, у меня есть приложение, которое удаленно выполняет сканирование на «x» количестве компьютеров, и каждое задание сканирования может содержать «y» количество определений отдельных заданий сканирования, которые необходимо запускать одно за другим. Фактическое сканирование выполняется отдельным EXE-файлом командной строки. При попытке запуска на двух компьютерах первое сканирование первого компьютера на долю секунды открывает окно командной строки, а затем немедленно закрывается, в то время как остальная часть процесса продолжается по назначению. Я перепробовал много вариантов одного и того же кода, и единственным надежным решением является создание потока.Sleep() внутри цикла foreach, что позволяет ему работать просто отлично.

Выполняемый код выглядит примерно так:

 private void StartClicked(object sender, MouseButtonEventArgs e)
{
    // Gather information about the job here

    Task.Factory.StartNew(() => RunJobs(listOfJobs), TaskCreationOptions.LongRunning)

    // Do some other stuff while tasks run.
}

private void RunJobs(Queue<Job> p_jobs)
{
    while (p_jobs.Any())
    {
        var job = p_jobs.Dequeue();
        Task.Factory.StartNew(() => BeginScan(job), TaskCreationOptions.LongRunning);
        // Adding Thread.Sleep(someNumber) here fixes the issue, but I don't want to rely on that.
    }
}

private void BeginScan(Job p_job)
{
    foreach(var scanPolicy in p_job.PoliciesForExecution)
    {
        PolicyScan(scanPolicy);
    }
}

private void PolicyScan(Policy p_policy)
{
    // Launch exe with some parameters here.
}
  

Что здесь не так? Почему добавление ручного потока.Sleep() устраняет проблему?

Комментарии:

1. Какой тип p_jobs ?

2. Кроме того, кажется, что вы на самом деле не занимаетесь асинхронным программированием, вам не следует создавать задачу с использованием Task.Factory.StartNew , а затем сразу же ожидать ее, что свяжет один поток, просто ожидающий завершения другой задачи. Вместо этого вы должны правильно использовать async / await .

3. p_jobs — это очередь<Задание> . Кроме того, вы правы в отношении немедленного ожидания в этом примере. У этого есть причина в реальном коде, но в примере она ничего не дает.

4. Если это не a ConcurrentQueue<T> , то это не потокобезопасно. Если вы ставите в очередь работу в эту очередь из других потоков, она, по-видимому, завершается случайным сбоем

5. Работа ставится в очередь до создания задачи, после этого ее ничто не изменяет (кроме удаления задачи из очереди в цикле).