how to cancel HostingEnvironment.QueueBackgroundWo

2019-07-18 08:14发布

问题:

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?

回答1:

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
    }
});


回答2:

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.