2016-08-05 17 views
0

キャンセルコードスニペットを使用した単純な非同期呼び出しです。コードはWPFアプリケーションクラス内にあります。 WPF UIコマンドを使用してCancelメソッドを呼び出すと、非同期メソッドが正常に終了します。ただし、OnExitメソッド中にキャンセルが呼び出された場合、何も起こりません。私の実際のコードでは、非同期メソッドが適切にクリーンアップされるべきIOリソースを使用するため、OnExit呼び出しが必要です。CancellationTokenSource.CancelがWPFアプリの終了時に機能しない

アイデア?

編集:予想される動作は、キャンセルが呼び出されたときにTask.DelayメソッドがOperationCancelledExceptionをスローする必要があることです。私が知りたいのは、なぜアプリケーションが終了しても、それが適切に動作するようにするための回避策がないのかということです。これは手で問題を解決するだろうが、あなたのポストされたコードのコンテキストごとに、まあ、おそらくあなたはトークンオブジェクトのIsCancellationRequestedプロパティを使用することができますし、取り消し要求のためにそのプロパティをチェックして、あなたの耳を傾けループから抜け出す場合

public partial class App : Application { 
    protected override void OnStartup(StartupEventArgs e) { 
     base.OnStartup(e); 
     ListenAsync(source.Token); 
    } 

    ManualResetEvent waitHandle = new ManualResetEvent(false); 
    CancellationTokenSource source = new CancellationTokenSource(); 

    public void Cancel() { 
     source.Cancel(); 
    } 

    async void ListenAsync(CancellationToken token) { 
     try { 
      while (true) { 
       await Task.Delay(300000, token); 
      } 
     } catch (OperationCanceledException) { 
      Console.WriteLine("Cancelled"); 
     } catch (Exception err) { 
      Console.WriteLine(err.Message); 
     } finally { 
      Console.WriteLine("Terminate"); 
      waitHandle.Set(); 
     } 
    } 

    protected override void OnExit(ExitEventArgs e) { 
     Cancel(); 
     waitHandle.WaitOne(); 
     base.OnExit(e); 
    } 
} 
+0

IOをクリーンアップする理由は何ですか?それは適切ではないと思う。 – Rahul

+0

実際のコードはIOクリーンアップを行います。上記のサンプルコードは、キャンセルを機能させるためのものです。 –

+0

ループが常時動作しているのではなく、[登録(アクションアクション)](https://msdn.microsoft.com/en-us/library/dd321635(v=vs.110) .aspx)、その内部にクリーンアップコードを入れます。 –

答えて

1

問題が見つかりました。

WPF App Exit中のキャンセル呼び出しは、ListenAsync関数と同じ同期コンテキストにあります。スレッドはwaitHandle.WaitOneによってブロックされるため、ListenAsyncメソッドが同じ同期コンテキストで実行を再開する方法はありません。

問題は、これがListenAsync機能の残りはTask.Delay機能の同期コンテキストに滞在することができます

await Task.Delay(300000, token).ConfigureAwait(false); 

に非同期呼び出しを変更することで解決することができます。

0

わかりませんlike

async void ListenAsync(CancellationToken token) { 
    try { 
     while (true) 
     { 
      if(token.IsCancellationRequested) 
       break; 

      await Task.Delay(300000, token); 
     } 
    } 
関連する問題