C# 为什么取消此CancellationToken?

C# 为什么取消此CancellationToken?,c#,azure-cloud-services,cancellationtokensource,C#,Azure Cloud Services,Cancellationtokensource,似乎在我调用第一个异步方法(GetBar()在本例中)之后,CancellationToken的IsCancellationRequested设置为true,但我不想这样,也不明白为什么会发生这种情况 这是一个Azure云服务工作者角色,如果这很重要的话 public class WorkerRole : RoleEntryPoint { private CancellationTokenSource cancellationTokenSource; private Task r

似乎在我调用第一个异步方法(
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云服务中实现的。知道为什么
iscancellationrequest
设置为true吗?

在等待
FooService.GetBar()
完成时,似乎调用了
OnStop
。也许可以添加某种形式的日志记录,以查看是否在
标记之间调用了
OnStop
var bar=wait…
返回确认后

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

要解决这个问题,你需要确保


除了您在
Run()
中显示的两行代码之外,
cancellationTokenSource
还可以多次调用哪些代码?如果我不得不猜测的话,我会说您在lambada中有一个带有
this.cancellationTokenSource.Token
的竞态条件,这导致传递到
Foo.Bar的标记(
与作为
Task.Run的第二个参数传递的标记不同(
您是否为
GetBar
引发了异常?请检查此项,看看是否有帮助:根据您的更新,在您等待
FooService.GetBar()时,是否可以调用
OnStop
要完成吗?也许可以添加某种形式的日志记录,以查看在
令牌之前是否调用了
OnStop
。ThrowIfCancellationRequested()
var bar=wait…
@ScottChamberlain是的,看起来
在顶部
被呼叫了,你完全正确。这很奇怪……我没料到。感谢你们两位的快速响应。编辑:请随意发布你最后的评论作为答案,我会接受。现在来解决为什么
正在调用OnStop
:)只是为了澄清一下,调用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
}