2016-09-21 57 views
2

我想RunAsync方法需要CancellationToken作爲一個很好的參數。 不幸的是,我的觀察我永遠不會被取消。服務結構RunAsync(CancellationToken cancellationToken)不會被取消

當然取消RunAsync方法調用OnCloseAsync將是一種多餘。 我還想知道何時(如果)取消實際發生。

我應該寫一些額外的代碼來提供一個工作的Stop()方法在我的客戶端?我會在者優先中的CancellationToken將RunAsync實際上被取消;-)

我的服務織物服務代碼:

/// <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

再次,執行此操作的一種方法是使用DeleteServiceAsync以編程方式刪除服務,使用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秒,並且在循環之外花了3秒,您可以看到爲什麼當您不在延遲範圍內時發生取消的可能性極小。

+2

* facepalm *你是對的...... – lapsus

+0

如果服務結構包含帶有CancellationToken的'RunAsync',爲什麼會有'CloseAsync'?你知道什麼時候該服務正在通過「RunAsync」右側的CancellationToken關閉? –

相關問題