据我所知,我有误导性的信息。我需要在后台运行一个单独的线程。
目前我这样做:
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
}
}
你会建议我回到这种方法来保证使用新线程吗?
答案 0 :(得分: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);
}
}
答案 1 :(得分:8)
这取决于您使用的调度程序。有两个库存实现,ThreadPoolTaskScheduler和SynchronizationContextTaskScheduler。后者根本不启动一个线程,由FromCurrentSynchronizationContext()方法使用。
ThreadPoolTaskScheduler就是你得到的。确实使用了LongRunning选项,如果设置了它将使用常规Thread。重要的是要避免使其他TP线程匮乏。你会得到一个没有选项的TP线程。这些是实施细节,如有更改,恕不另行通知,但我认为不太可能很快。
答案 2 :(得分:4)
您必须指定为什么您“总是需要一个单独的线程”。
void Main()
{
var task = Task.Factory.StartNew(CheckFiles,
cancelCheckFile.Token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
task.Wait();
}
智能调度程序将在此处使用1个线程。为什么不呢?
但一般来说,CheckFiles()方法将在另一个(而不是调用)线程上执行。问题在于是否特别创建了该线程,或者它是否甚至可以在多个线程上执行(连续)。
当您使用任务时,您放弃对线程的控制。这应该是一件好事。