为什么这个 CancellationToken 被取消了?

Why is this CancellationToken getting cancelled?

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

如果重要的话,这是 Azure 云服务工作者角色。

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 吗?

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

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

要解决问题,您需要确保the overridden Run method does not return till the work is complete

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
}