Есть ли смысл начинать задание LongRunning, если родитель сразу ждет? - PullRequest
1 голос
/ 27 января 2020

Я работаю над устаревшим кодом, который неоднократно вызывает долгосрочную задачу в новом потоке:

var jobList = spGetSomeJobIds.ToList();

jobList.ForEach((jobId) =>
{
    var myTask = Task.Factory.StartNew(() => CallExpensiveStoredProc(jobId), 
        TaskCreationOptions.LongRunning);
    myTask.Wait();
});

Поскольку вызывающий поток немедленно вызывает Wait и блокирует, пока задача не завершится, я не могу увидеть любую точку в коде Task.Factory.StartNew. Я что-то пропустил? Есть ли что-то в TaskCreationOptions.LongRunning, что может добавить ценность?

1 Ответ

0 голосов
/ 27 января 2020

Как гласит msdn:

Ожидает завершения задания. Кроме того,

, есть следующий оператор:

Wait блокирует вызывающий поток до завершения задачи.

Так что myTask.Wait(); выглядит избыточным, поскольку метод CallExpensiveStoredProc ничего не возвращает.

Как Рекомендуется использовать операторы async и await при работе с асинхронными операциями, такими как операции с базами данных.

ОБНОВЛЕНИЕ:

Что мы have is:

  1. Мы запускаем LongRunning, поэтому создается новый поток. Видно в исходных файлах .

  2. Тогда мы называем myTask.Wait();. Этот метод просто ждет, когда myTask завершит sh свою работу. Таким образом, все jobList итераций будут выполняться последовательно, а не параллельно . Итак, теперь нам нужно решить, как должна выполняться наша работа - последовательно ( case A ) или параллельно ( case B ).

Случай A: Последовательное выполнение наших заданий

Если ваши задания должны выполняться последовательно, то может возникнуть несколько вопросов:

  • зачем мы используем многопоточность , если наш код выполняется последовательно? Наш код должен быть чистым и простым. Таким образом, мы можем избежать использования многопоточности в этом случае
  • , когда мы создаем новый поток, мы добавляем дополнительные издержки в пул потоков. Потому что пул потоков пытается определить оптимальное количество потоков и создает как минимум один поток на ядро. Это означает, что, когда все потоки пула потоков заняты, задача может ждать (в крайних случаях бесконечно долго), пока она фактически не начнет выполняться. кейс для создания нового Thread, особенно нового потока, используя LongRunning enum.

    кейс B: параллельное выполнение наших заданий

    Если наша цель - запустить все параллельных заданий, тогда myTask.Wait(); следует исключить, потому что это делает код для последовательного выполнения.

    Код для проверки:

    var jobs = new List<int>(){1, 2, 3 };
    jobs.ForEach(j => 
       {
           var myTask = Task.Factory.StartNew(() => 
           {
               Console.WriteLine($"This is a current number of executing task: { j }");
               Thread.Sleep(5000); // Imitation of long-running operation
               Console.WriteLine($"Executed: { j }");
           },  TaskCreationOptions.LongRunning);
           myTask.Wait();
        });
    Console.WriteLine($"All jobs are executed");
    

    Чтобы заключить в этом случае B, нет никакой выгоды для создать новую тему, особенно новую тему, используя LongRunning enum. Потому что это дорогостоящая операция, которая занимает много времени на создание и потребление памяти.

...