ほとんどの場合、非同期コードのブロックは不承認となります。Thread.Sleep()とTask.Yield()で非同期でブロックする
しかし、WPFアプリケーションでバックグラウンドタスクを実行しています。 ユーザーがウィンドウを閉じると、このタスクはキャンセルされ、キャンセルとその後のクリーンアップが完了するまでウィンドウの終了が遅延されます。その間に、それ以上のユーザー入力はブロックする必要があります。
しよう&を検索するビットの後、私は次のコードを思い付いた:
ViewModel.cs:
async void RunTaskAsync()
{
_cancelTknSource = new CancellationTokenSource();
try {
await Task.Run(/*...long running calculation...*/, _cancelTknSource.Token);
}
catch (OperationCanceledException) { }
finally {
/*...cleanup...*/
_cancelTknSource.Dispose();
_cancelTknSource = null;
}
}
async Task CancelAsync()
{
_cancelTknSource?.Cancel();
while (_cancelTknSource != null) {
Thread.Sleep(10);
await Task.Yield(); //prevents dead-lock
}
}
Window.xaml.cs:
async void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
await DataContext.CancelAsync();
Close();
}
(すべてのこれらのメソッドはUIスレッドから呼び出されます)
これは良い方法ですか? そうでない場合、代替案は何ですか?
ようこそ。私はStackExchangeネットワーク上で、この質問が兄弟館のサイト_Code Review_(なぜあなたの問題は問題ではなくデザインなので)で尋ねられるのだろうか?幸運 – MickyD
Task.Yield()はデッドロックを修正せず、UIスレッドが通知を処理できなくなるという基本的な問題を解決しません。 WPFのアドバイスは基本的に[Winformsとは異なる](https://stackoverflow.com/a/1732361/17034)ではありません。 –
"Task.Runを待つ(/ * ...長時間実行中の計算... * /、_ cancelTknSource.Token);"あなたがこの仕事を待っているならば。トークンのポイントは何ですか? – efekctive