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
}