#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. Работа ставится в очередь до создания задачи, после этого ее ничто не изменяет (кроме удаления задачи из очереди в цикле).