使用Task.StartNew方法时如何保证创建新线程

Jon*_*Jon 13 .net c# multithreading .net-4.0 task-parallel-library

据我所知,我有一些误导性的信息.我需要在后台运行一个单独的线程.

目前我这样做:

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
    }
 }
Run Code Online (Sandbox Code Playgroud)

这总是为我创建一个新线程.但经过多次讨论后,即使将其标记为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
   }
}
Run Code Online (Sandbox Code Playgroud)

你会建议我回到这种方法来保证使用新线程吗?

Alo*_*aus 16

默认任务调度程序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);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我没有看到我的答案有什么问题.你能详细说明你对downvote的推理是什么吗? (3认同)
  • @Ramhound我意识到这很古老,但是xp!=正确答案.Alois是正确的,请参阅`ThreadPoolTask​​Scheduler`的.NET Framework源代码 - 第二个方法`QueueTask`:referencesource.microsoft.com/#mscorlib/system/threading/Tasks/ThreadPoolTask​​Scheduler.cs代码中甚至还有一个注释://在自己的专用线程上运行LongRunning任务. (3认同)

Han*_*ant 8

这取决于您使用的调度程序.有两个库存实现,ThreadPoolTask​​Scheduler和SynchronizationContextTaskScheduler.后者根本不启动一个线程,由FromCurrentSynchronizationContext()方法使用.

ThreadPoolTask​​Scheduler就是你得到的.确实使用了LongRunning选项,如果设置了它将使用常规Thread.重要的是要避免使其他TP线程匮乏.你会得到一个没有选项的TP线程.这些是实施细节如有变更,恕不另行通知,但我认为不太可能很快.


Nic*_*ler 5

LongRunning只是调度程序的一个提示 - 如果你必须总是有一个新的Thread,你将不得不创建一个.

  • 正如你已经发现的那样,确实有"神奇的"隐藏线索.但真正的问题是,为什么要保证它将如何执行?如果任务调度程序有理由相信可能不需要新的线程,为什么你会认为你知道更好?这样的决定背后有很多理论和权衡. (2认同)