2017-09-05 29 views
0

我需要一個再入任務,並執行類似的代碼https://blogs.msdn.microsoft.com/lucian/2014/03/03/async-re-entrancy-and-the-patterns-to-deal-with-it/(模式5)重入模式5:將取消先前調用

但我想知道如果CancellationTokenSource處置是不缺的。我的實施將其添加進來。繼續使用

private Task _fooAsyncTask; 
    private CancellationTokenSource _fooAsyncCancellation; 

    public async Task Button1Click() 
    { 
     // Assume we're being called on UI thread... if not, the two assignments must be made atomic. 
     // Note: we factor out "FooHelperAsync" to avoid an await between the two assignments. 
     // without an intervening await. 
     _fooAsyncCancellation?.Cancel(); 
     _fooAsyncCancellation = new CancellationTokenSource(); 
     _fooAsyncTask = FooHelperAsync(_fooAsyncCancellation.Token); 

     await _fooAsyncTask.ContinueWith(task => 
     { 
      _fooAsyncCancellation.Dispose(); 
      _fooAsyncCancellation = null; 
     }); 
    } 

    private async Task FooHelperAsync(CancellationToken cancel) 
    { 
     try { if (_fooAsyncTask != null) await _fooAsyncTask; } 
     catch (OperationCanceledException) { } 
     cancel.ThrowIfCancellationRequested(); 
     await FooAsync(cancel); 
    } 

    private async Task FooAsync(CancellationToken cancel) 
    { 
     // 
    } 

這是正確的嗎?

+0

沒有必要處置CTS。你可以處置它,但沒有背後的非託管資源,它是值得處置的。順便說一句,你並不需要一個延續,只是等待_fooAsyncTask –

+0

第二次看後,不建議處置CTS - 如果你這樣做,你將獲得* _fooAsyncCancellation異常.Cancel(); * –

+0

@SirRufo「它不建議處置CTS「 - 你有沒有參考。我只是尋找有關此事的一些「最佳實踐」 ...... – Fildor

回答

0

您應該更改您的代碼

  • 設置_ fooAsyncCancellationnull UI線程(在延續它不是)
  • 保證,你處理你任務創建的CTS 。

這裏修改後的代碼

Task _fooAsyncTask; 
CancellationTokenSource _fooAsyncCancellation; 

async void button1_Click(object sender, EventArgs e) 
{ 
    _fooAsyncCancellation?.Cancel(); 
    using (var cts = new CancellationTokenSource()) 
    { 
     _fooAsyncCancellation = cts; 

     try 
     { 
      await FooAsyncHelper(cts.Token); 
     } 
     catch (OperationCanceledException) { } 

     if (_fooAsyncCancellation == cts) 
     { 
      _fooAsyncCancellation = null; 
     } 
    } 
} 

async Task FooAsyncHelper(CancellationToken cancellationToken) 
{ 
    try 
    { 
     if (_fooAsyncTask != null) 
     { 
      await _fooAsyncTask; 
     } 
    } 
    catch (OperationCanceledException) { } 
    cancellationToken.ThrowIfCancellationRequested(); 
    await FooAsync(cancellationToken); 
} 

async Task FooAsync(CancellationToken cancellationToken) 
{ 
    // just some sample work to do 
    for (int i = 0; i < 100; i++) 
    { 
     await Task.Delay(100); 
     cancellationToken.ThrowIfCancellationRequested(); 
    } 
} 
+0

不知道明白了,你的第一個評論 – Chris