2016-09-21 1 views
2

メソッドがCancellationTokenを引数として取ると考えました。 残念ながら私の観察には私は決してキャンセルされません。もちろんサービスファブリックRunAsync(CancellationToken cancellationToken)が取り消されない

OnCloseAsyncは、一種の冗長になるの呼び出しRunAsync方法をキャンセルします。 まだ取り消しが実際に起こったかどうかは不思議です。

私はクライアントで動作中のStop()メソッドを提供するためにいくつかの追加コードを書いていますか?私は実際にキャンセルされるだろうRunAsyncでcancellationToken ;-)

マイサービスファブリックサービス好まだろうコード:

/// <summary> 
/// This is the main entry point for your service instance. 
/// </summary> 
/// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service instance.</param> 
protected override async Task RunAsync(CancellationToken cancellationToken) 
{ 
    // TODO: Replace the following sample code with your own logic 
    //  or remove this RunAsync override if it's not needed in your service. 

    long iterations = 0; 

    while (!cancellationToken.IsCancellationRequested) 
    { 
     // I commented this out because I want my client to handle the cancellation 
     // event gracefully without throwing an OperationCanceled exception. 
     //cancellationToken.ThrowIfCancellationRequested(); 

     // I never found these messages in any logs. Nor in the diagnostics events window in Visual Studio. 
     ServiceEventSource.Current.ServiceMessage(this, "Working-{0}", ++iterations); 

     await _client.Start(cancellationToken); 

     await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); 
    } 
} 

マイサンプルクライアント実装:

public class Client 
{ 
    private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); 

    public async Task Start(CancellationToken cancellationToken = default(CancellationToken)) 
    { 
     while (!cancellationToken.IsCancellationRequested) 
     { 
      _logger.Info("Saying hello from Main Operation."); 
      await Task.Delay(3000, cancellationToken); 
     } 

     _logger.Info("Cancellation requested. Shutting down MainOperation()."); 
    } 

    public void Stop() 
    { 
     _logger.Info("Stop requested. But I have no means to stop. Not implemented."); 
    } 
} 
+0

また、これを行う方法の1つは、サービスの終了時にDeleteServiceAsyncを使用してプログラムで削除することです。CreateServiceAsyncを使用してサービスを再作成することもできます。 – LoekD

+0

しかし、私はService Fabric以外のコードを実行したくありません。 OnCloseAsyncも呼び出されていますが、これは問題ありません。私はそれを使って作業することができます。それでもRunAsyncのcancellationTokenが "キャンセル"に設定されているのは不思議です。 – lapsus

+0

他のサービスから呼び出すことができます。また、サービスの停止、アップグレード、セカンダリからプライマリレプリカへの移動、および/またはクラスタ内での再配置の際に呼び出されます。 – LoekD

答えて

3

はい、キャンセルトークンは実際にキャンセルされます。それは保証されています。私はあなたに何年ものテストと生産の使用の後、あなたに保証することができます、これは見落としではありません。

ただし、コードに見落としがあります。

あなたのクライアントからこのトレース出力を見ることを期待している場合:

_logger.Info("Cancellation requested. Shutting down MainOperation()."); 

あなたはしません、むしろ、それはあなたがそれを今まで表示されます極めてはほとんどありません。どうして?キャンセルトークンが遅延中に通知されたときに

await Task.Delay(3000, cancellationToken); 

OperationCanceledExceptionがスローされます。それ以前にこの行があるため。これにより、ループから外してRunAsyncから抜け出し、ロギング・ラインは実行されません。

遅延内で3秒、ループ内でその外側にナノ秒を費やしているため、遅延内にないときにキャンセルが発生する可能性はほとんどありません。

+2

* facepalm *あなたは大丈夫です... – lapsus

+0

サービスファブリックにCancellationTokenで 'RunAsync'が含まれていると、なぜそれが' CloseAsync'ですか? RunAsyncのCancellationTokenでサービスがシャットダウンしているのを知っていますか? –

関連する問題