为什么这个CancellationToken会被取消

本文关键字:取消 CancellationToken 为什么 | 更新日期: 2023-09-27 18:13:45

似乎就在我调用我的第一个异步方法(GetBar()在这个例子中)之后,CancellationToken的IsCancellationRequested被设置为true,但我不希望这样,也不明白为什么会发生。

这是一个Azure Cloud Service worker角色,如果重要的话。

public class WorkerRole : RoleEntryPoint
{
    private CancellationTokenSource cancellationTokenSource;
    private Task runTask;
    public override void Run()
    {
        this.cancellationTokenSource = new CancellationTokenSource();
        this.runTask = Task.Run(() => Foo.Bar(this.cancellationTokenSource.Token), this.cancellationTokenSource.Token);
    }
    public override void OnStop()
    {
        this.cancellationTokenSource.Cancel();
        try
        {
            this.runTask.Wait();
        }
        catch (Exception e)
        {
            Logger.Error(e, e.Message);
        }
        base.OnStop();
    }
    // ... OnStart omitted
}
public static class Foo
{
    public static async Bar(CancellationToken token)
    {
        while (true)
        {
            try
            {
                token.ThrowIfCancellationRequested();
                var bar = await FooService.GetBar().ConfigureAwait(false);
                // Now token.IsCancellationRequested == true. Why? The above call does not take the token as input.
            }
            catch (OperationCanceledException)
            {
                // ... Handling
            }
        }
    }
}

我曾经在另一个项目中成功地使用过一次CancellationTokens,我在这里使用了类似的设置。我所知道的唯一区别是这是在Azure云服务中。知道为什么IsCancellationRequested被设为true吗?

为什么这个CancellationToken会被取消

当您等待FooService.GetBar()完成时,OnStop似乎被调用了。也许可以添加某种形式的日志记录,以查看token.ThrowIfCancellationRequested();之间和var bar = await ...返回确认之后是否调用了OnStop

这就是导致令牌被取消的原因。

要解决这个问题,您需要确保覆盖的Run方法在工作完成之前不会返回。

public override void Run()
{
    this.cancellationTokenSource = new CancellationTokenSource();
    this.runTask = Task.Run(() => Foo.Bar(this.cancellationTokenSource.Token), this.cancellationTokenSource.Token);
    this.runTask.Wait(); //You may need a try/catch around it
}