为什么新的Service Fabric代码的示例RunAsync构造如下
protected override async Task RunAsync(CancellationToken cancellationToken)
{
while(true)
{
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
}
而不是
protected override async Task RunAsync(CancellationToken cancellationToken)
{
while(cancellationToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
}
没有抛出的版本不是首选吗? The docs声明两种实现都是正确的:“系统将等待您的任务结束(通过成功完成,取消或故障)”。
答案 0 :(得分:4)
简短回答 - 两者都很好。我使用ThrowIfCancellationRequested
,因为IMO是更安全的选择。它也更加一致 - 调用链中较低的方法可以通过异常传播取消。
每当RunAsync
中发生异常时,Service Fabric reports发生一个瞬态错误(这意味着重新启动服务而不重新创建实例/副本)。
它为OperationCanceledException
提供了特殊处理 - 如果它被传递给方法的取消令牌抛出,则认为该方法已被成功取消,并且不会报告任何错误。
您可以通过监控Microsoft-ServiceFabric-Services
ETW事件来自行尝试。
答案 1 :(得分:0)
cancelToken.ThrowIfCancellationRequested();
等于
if(令牌。IsCancellationRequested) 抛出新的OperationCanceledException(token);
通常,人们将其用作一种控制机制,以确保当前处理被中止而不会潜在地运行任何额外的代码。另外,调用ThrowIfCancellationRequested()时无需检查取消情况
答案 2 :(得分:0)
这甚至更简单,也可以工作:
protected override async Task RunAsync(CancellationToken cancellationToken)
{
while(true)
{
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
}
或
protected override async Task RunAsync(CancellationToken cancellationToken)
{
while(cancellationToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
我发现了这一点,因为我的代码是按照如下示例代码建模的:
protected override async Task RunAsync(CancellationToken cancellationToken)
{
var pipeline = ...
pipeline.Start();
while (true) {
if (cancellationToken.IsCancellationRequested) {
ServiceEventSource.Current.ServiceMessage(Context, "Stopping pipeline");
await pipeline.ShutdownAsync();
}
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
}
并且管道从未停止过。解决方案是不使用cancellationToken
调用中的Task.Delay
。