From what I can tell I have misleading bits of information. I need to have a separate thread running in the background.
At the moment I do it like this:
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
}
}
This always creates a new thread for me. However after several discussions even if it is marked as LongRunning doesn't guarantee that a new thread will be created.
In the past I have done something like this:
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
}
}
Would you recommend that I go back to this approach to guarantee a new thread is used?
LongRunning is just a hint to the scheduler - if you absolutely must always have a new Thread, you will have to create one.
The default task scheduler ThreadPoolTaskScheduler
does indeed always create a new thread for long running task. It does not use the thread pool as you can see. It is no different as the manual approach to create the thread by yourself. In theory it could happen that the thread scheduler of .NET 4.5 does something different but in practice it is unlikely to change.
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);
}
}
It depends on the Scheduler you use. There are two stock implementations, ThreadPoolTaskScheduler and SynchronizationContextTaskScheduler. The latter doesn't start a thread at all, used by the FromCurrentSynchronizationContext() method.
The ThreadPoolTaskScheduler is what you get. Which indeed uses the LongRunning option, it will use a regular Thread if it set. Important to avoid starving other TP threads. You'll get a TP thread without the option. These are implementation details subject to change without notice, although I'd consider it unlikely anytime soon.
You'll have to specify why you "always need a separate thread".
void Main()
{
var task = Task.Factory.StartNew(CheckFiles,
cancelCheckFile.Token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
task.Wait();
}
A smart scheduler will use 1 thread here. Why shouldn't it?
But in general the CheckFiles() method will be executed on another (than the calling) thread. The issue is whether that thread is especially created or whether it might even be executed on several threads (in succession).
When you are using Tasks you give up control over the Thread. And that should be a good thing.