HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Cancelable thread worker

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
cancelablethreadworker

Problem

My goal was to create class, that can run external method in non blocking manner.
Second requirement was to be able to abort method run if it is needed (i.e. running user script).
I decided to do that with Thread instead of Task, because only Thread can be truly aborted.
Because Thread have big creation overhead, it is initialized and started in advance and resumed if work is needed.

What do you think about my implementation ?

Example usage:

//generic type param is used as external method argument (instead of object)
AbortableStepWorker worker = new AbortableStepWorker(someMethodWithIntArgument);
worker.Start();
worker.DoWork(someArgument);
while(!worker.WaitForWorkDone(someTimeout))
    if(cancelWasRequested)
    {
        worker.Stop(lastChanceTimeout);
        return false;
    }

//if we've managed to get here, then work was done
//run result:
var result = !worker.Stopped;


and class implementation:

```
public class AbortableStepWorker : IDisposable
{
public AbortableStepWorker(Func externalWork)
{
if (externalWork == null) throw new ArgumentNullException("workMethod");
this.externalWork = externalWork;

ThreadInstance = new Thread(Worker) { Priority = ThreadPriority.BelowNormal };
}

private readonly Func externalWork;
private T externalWorkParam;
private void Worker()
{
try
{
while (true)
{
resumeEvent.WaitOne(Timeout.Infinite);

if (stopRequested)
return;

if (!externalWork(externalWorkParam))
return;

workDoneEvent.Set();
}
}
catch (ThreadAbortException) { }
finally { workDoneEvent.Set(); }
}

private bool stopRequested = false;
private AutoResetEvent resumeEvent = new AutoResetEvent(false);

Solution

You should never use Thread.Abort(). If you don't have control over the code that's executing in the thread, then you don't know what will that abort do. It's quite possible it will leave some object in an inconsistent state, or something like that. If you do have control over the code, you should instead use cooperative cancellation using CancellationToken.

Context

StackExchange Code Review Q#16036, answer score: 6

Revisions (0)

No revisions yet.