Подтвердить что ты не робот

Как гарантировать, что новый поток создается при использовании метода Task.StartNew

Из того, что я могу сказать, у меня есть вводящие в заблуждение биты информации. Мне нужно, чтобы в фоновом режиме выполнялся отдельный поток.

В настоящий момент я делаю это так:

var task = Task.Factory.StartNew
         (CheckFiles
          , cancelCheckFile.Token
          , TaskCreationOptions.LongRunning
          , TaskScheduler.Default);//Check for files on another thread

 private void CheckFiles()
 {
    while (!cancelCheckFile.Token.IsCancellationRequested)
    {
        //do stuff
    }
 }

Это всегда создает для меня новый поток. Однако после нескольких обсуждений, даже если он отмечен как LongRunning, не гарантирует, что будет создан новый поток.

В прошлом я сделал что-то вроде этого:

thQueueChecker = new Thread(new ThreadStart(CheckQueue));
thQueueChecker.IsBackground = true;
thQueueChecker.Name = "CheckQueues" + DateTime.Now.Ticks.ToString();
thQueueChecker.Start();


private void CheckQueue()
{
   while (!ProgramEnding)
   {
            //do stuff
   }
}

Рекомендуете ли вы вернуться к этому подходу, чтобы гарантировать использование нового потока?

4b9b3361

Ответ 1

LongRunning - это всего лишь подсказка для планировщика - если вы абсолютно обязательно должны иметь новый поток, вам придется его создать.

Ответ 2

Планировщик заданий по умолчанию ThreadPoolTaskScheduler действительно всегда создает новый поток для долговременной задачи. Он не использует пул потоков, как вы можете видеть. Это ничем не отличается от ручного подхода к созданию потока самостоятельно. Теоретически может случиться, что планировщик потоков .NET 4.5 делает что-то другое, но на практике он вряд ли изменится.

protected internal override void QueueTask(Task task)
{     
  if ((task.Options & TaskCreationOptions.LongRunning) != TaskCreationOptions.None)
  {
    new Thread(s_longRunningThreadWork) { IsBackground = true }.Start(task);
  }
  else
  {
    bool forceGlobal = 
        (task.Options & TaskCreationOptions.PreferFairness) != TaskCreationOptions.None;
     ThreadPool.UnsafeQueueCustomWorkItem(task, forceGlobal);
  }
}

Ответ 3

Это зависит от используемого Планировщика. Существуют две реализации запаса: ThreadPoolTaskScheduler и SynchronizationContextTaskScheduler. Последний не запускает нить вообще, используемый методом FromCurrentSynchronizationContext().

ThreadPoolTaskScheduler - это то, что вы получаете. В котором действительно используется опция LongRunning, он будет использовать обычный поток, если он установлен. Важно избегать голодания других нитей ТР. Вы получите поток TP без опции. Это детали реализации, которые могут быть изменены без предварительного уведомления, хотя в ближайшее время я считаю это маловероятным.

Ответ 4

Вам нужно указать, почему вам "всегда нужен отдельный поток".

void Main()
{
   var task = Task.Factory.StartNew(CheckFiles, 
     cancelCheckFile.Token, 
     TaskCreationOptions.LongRunning, 
     TaskScheduler.Default);

   task.Wait();
}

В интеллектуальном планировщике будет использоваться 1 поток. Почему это не должно быть?


Но в целом метод CheckFiles() будет выполняться на другом (чем вызывающем) потоке. Проблема заключается в том, что этот поток особенно создан или он может даже выполняться на нескольких потоках (последовательно).

Когда вы используете Tasks, вы отказываетесь от контроля над Thread. И это должно быть хорошо.