In a thread, I create some System.Threading.Task
and start each task.
When I do a .Abort()
to kill the thread, the tasks are not aborted.>
You can abort a task like a thread if you can cause the task to be created on its own thread and call Abort
on its Thread
object. By default, a task runs on a thread pool thread or the calling thread - neither of which you typically want to abort.
To ensure the task gets its own thread, create a custom scheduler derived from TaskScheduler
. In your implementation of QueueTask
, create a new thread and use it to execute the task. Later, you can abort the thread, which will cause the task to complete in a faulted state with a ThreadAbortException
.
Use this task scheduler:
class SingleThreadTaskScheduler : TaskScheduler
{
public Thread TaskThread { get; private set; }
protected override void QueueTask(Task task)
{
TaskThread = new Thread(() => TryExecuteTask(task));
TaskThread.Start();
}
protected override IEnumerable GetScheduledTasks() => throw new NotSupportedException(); // Unused
protected override bool NotSupportedException(Task task, bool taskWasPreviouslyQueued) => throw new NotSupportedException(); // Unused
}
Start your task like this:
var scheduler = new SingleThreadTaskScheduler();
var task = Task.Factory.StartNew(action, cancellationToken, TaskCreationOptions.LongRunning, scheduler);
Later, you can abort with:
scheduler.TaskThread.Abort();
Note that the caveat about aborting a thread still applies:
The
Thread.Abort
method should be used with caution. Particularly when you call it to abort a thread other than the current thread, you do not know what code has executed or failed to execute when the ThreadAbortException is thrown, nor can you be certain of the state of your application or any application and user state that it is responsible for preserving. For example, callingThread.Abort
may prevent static constructors from executing or prevent the release of unmanaged resources.