使用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 } } 

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

LongRunning只是调度程序的一个提示 – 如果你绝对必须有一个新的Thread,你将不得不创建一个。

默认任务调度程序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); } } 

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

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

您必须指定“始终需要单独的线程”的原因。

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

智能调度程序将在此处使用1个线程。 为什么不呢?


但一般来说,CheckFiles()方法将在另一个(而不是调用)线程上执行。 问题在于是否特别创建了该线程,或者它是否甚至可以在多个线程上执行(连续)。

当您使用任务时,您放弃对线程的控制。 这应该是一件好事。