2017-09-05 11 views
0

私は再入国タスクを必要とし、https://blogs.msdn.microsoft.com/lucian/2014/03/03/async-re-entrancy-and-the-patterns-to-deal-with-it/のようなコードを実装する(パターン5)リエントラントパターン5:以前の呼び出しを取り消す

が、CancellationTokenSourceの処分が欠落していない場合、私は思ったんだけど。私の実装は.ContinueWithで追加しています

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 "it CTSを処分することはお勧めしません。 " - あなたはそのためにレフェリングをしていますか?私はそのことに関していくつかの「ベストプラクティス」を探していただけです... – Fildor

答えて

0

あなたは

  • にコードを変更する必要がありますが、あなたがそのタスク用に作成されたCTSを設けること、_ fooAsyncCancellation
  • (継続中で、それはありません)UIスレッド上nullへの保証を設定します。

ここで変更されたコード

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

関連する問題