Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to cancel HostingEnvironment.QueueBackgroundWorkItem

Is there a way to cancel background task made with HostingEnvironment.QueueBackgroundWorkItem?

There is CancellationToken which notifies if tasks was cancelled but how can i do it? Refering to https://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx

A successful cancellation involves the requesting code calling the CancellationTokenSource.Cancel method

OK. Where can i get access to CancellationTokenSource?

like image 671
maxlego Avatar asked May 14 '16 10:05

maxlego


2 Answers

After few trials i came up with the soulution:

HostingEnvironment.QueueBackgroundWorkItem(ct =>
{
    var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(ct);
    var cancellationToken = linkedTokenSource.Token;
    return Task.Factory.StartNew(() =>
    {
         // do stuff on background
    }, cancellationToken);
});

Update:

Indeed, task is not needed. Thanks svick for bringing that up. Here is a bit more detailed code sample without task.

HostingEnvironment.QueueBackgroundWorkItem(ct =>
{
    var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(ct);
    // following is a dummy method, but you get the idea.
    // StoreCancellationTokenSourceSoItCanBeUsedSomewhereElse(linkedTokenSource);

    var cancellationToken = linkedTokenSource.Token;

    try
    {
        while(true)
        {
            cancellationToken.ThrowIfCancellationRequested();
            // do bg stuff
        }
    }
    catch (OperationCanceledException ex)
    {
        // either token is in cancelled state
    }
});
like image 58
maxlego Avatar answered Nov 09 '22 13:11

maxlego


The signature of HostingEnvironment.QueueBackgroundWorkItem is:

public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem)

This means that a work item gets access to a CancellationToken. But I don't think that's useful in your case. From the documentation:

The provided CancellationToken will be signaled when the application is shutting down.

If you want to cancel the workItem based on some other condition, you can use a separate CancellationToken, which you create from a CancellationTokenSource. For example, to cancel a work item if it doesn't start within 10 seconds:

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));

HostingEnvironment.QueueBackgroundWorkItem(_ =>
{
    cts.Token.ThrowIfCancellationRequested();

    // the code of the work item goes here
});

This will technically still start the work item, even if the CancellationToken is cancelled, but it won't do anything.

Note that cancellation is always cooperative. This means that if you have a long-running work item, and you want to cancel it in the middle of its execution, you will need to keep checking the CancellationToken periodically.

like image 35
svick Avatar answered Nov 09 '22 13:11

svick