如何取消 HostingEnvironment.QueueBackgroundWorkItem

how to cancel HostingEnvironment.QueueBackgroundWorkItem

有没有办法取消使用 HostingEnvironment.QueueBackgroundWorkItem 进行的后台任务?

CancellationToken 通知任务是否被取消,但我该怎么做? 参考https://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx

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

好的。我在哪里可以访问 CancellationTokenSource

经过几次尝试,我想出了解决方案:

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

更新:

的确,不需要任务。感谢 svick 提出这个问题。 这是没有任务的更详细的代码示例。

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

HostingEnvironment.QueueBackgroundWorkItem的签名是:

public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem)

这意味着工作项可以访问 CancellationToken。但我认为这对你的情况没有用。来自 the documentation:

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

如果您想根据其他条件取消 workItem,可以使用从 CancellationTokenSource 创建的单独的 CancellationToken。例如,如果工作项未在 10 秒内启动,则取消该工作项:

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

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

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

这在技术上仍将启动工作项,即使 CancellationToken 已取消,但它不会执行任何操作。

请注意,取消始终是合作的。这意味着如果您有一个长 运行 的工作项,并且您想在执行过程中取消它,您将需要定期检查 CancellationToken