2017-01-13 1 views
2

自分のコードでタスクをスケジュールし、すぐにForeverRunningTaskAsyncに進みます。実行時にタスクをスケジュールしてC#で続ける

private async void button_Click(object sender, RoutedEventArgs e) 
{ 
    Task.Delay(5000).ContinueWith((t) => { StopForeverRunningTask(); }, CancellationToken.None); 
    await ForeverRunningTaskAsync(); 
} 

すべての作業罰金:ForeverRunningTaskAsyncは5秒間、すでに進行中である間、この方法StopForeverRunningTaskが実行されます。しかし、コンパイラはTask.Delayコールで 'await'を逃したと警告しています。 ForeverRunningTaskAsyncは遅延の後ではなく、すぐに開始する必要があるため、私は待つ必要はありません。おそらく、タスクをスケジューリングし、後続のコードにすぐに進むより洗練された方法がありますか?または、警告を無視するだけでいいですか?

編集: StopForeverRunningTaskは実際に何かを行うことができます。答えから、私はそれのより抽象的な名前を提供する必要があります参照してください。必ずしもForeverRunningTaskの実行を停止するとは限りません。いくつかのフラグを設定したり、現在の状態を取得したりすることができます(また、ForeverRunningTaskランタイム中に複数回呼び出されることもあります)ので、CancellationTokenの使用はオプションではありません。 WaitAllのアプローチは私の質問に答えて以下の提案。

+0

を完了するまで待つことである私が、私はなぜあなたはawait'全く '使用している、この質問を理解していませんか?あなたは 'ForeverRunningTaskAsync'の結果を使用していませんし、完了しても何もしていないのですが、これは単純に2つの異なるタスクを開始するのでしょうか? –

+0

私はちょうどこれらの2つに焦点を合わせました(長時間実行タスクと長時間実行タスクの流れを何らかの形で制御または調べるタスク)。長期実行タスクの前後には他のタスクがあり、長期実行タスクには結果などが実際にあります。私は、重要ではない細部を脇に置くことを可能な限り単純な例にしたいと思っていました。 – Alex

+2

@Alex: 'ContinueWith'は使用しないでください。別の 'async'メソッドを作成し、代わりに' await'を使用してください。 –

答えて

1

この種の警告は無視するのが一般的には好ましくありません。状況によっては(あなたの場合のような)明らかな即時の影響はないかもしれませんが、コードはその周りの変更に対して脆弱です。

あなたが持っている選択肢の一つは、両方のタスクが

private async void button_Click(object sender, RoutedEventArgs e) 
{ 
    var stopper = Task.Delay(5000).ContinueWith((t) => { StopForeverRunningTask(); }, CancellationToken.None); 
    var runner = ForeverRunningTaskAsync(); 
    await Task.WhenAll(stopper, runner); 
} 
3

あなたのコードには、すでにCancellationTokenの代わりにこれを行うヒントがあります。

5秒で自動キャンセルされますCancellationTokenを作成します。

using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5))) 
{ 
    await ForeverRunningTaskAsync(cts.Token); 
} 

次に、あなたのForeverRunningTaskAsync()法にような何か:それはかなりあなたのコードやモデルに適合しない場合は

async Task ForeverRunningTaskAsync(CancellationToken cancellationToken) 
{ 
    while (!cancellationToken.IsCancellationRequested) 
    { 
     // Do stuff, including passing cancellationToken on to anything 
     // else that supports it 
    } 
} 

をキャンセルトークンを使用する他の同様の方法がありますが、私は上記が標準であることを示唆しています。

+0

おそらく、私はメソッドのより良い名前を提供していたはずです。実際のコードでは、実際に長時間実行されるメソッドをキャンセルする必要はありませんが、より多くのデータを提供する(または実行の途中結果を取得する)のが好きです。私。 StopForeverRunningTaskは実際にはSomethingWhichDealWithsPropsOfForeverRunningTaskです。それでも、この質問の見解から、あなたの答えは絶対的に正しいので、私はそれを上書きしました。ありがとう! – Alex

+1

ここにいる人はあなたが質問した質問ではなく、あなたが聞いた質問にしか答えられないことに注意してください。実際に他のタスクをキャンセルする必要がない場合は、あなたの実際の要求にもっと忠実な質問を書くべきでしょう。 –

+0

はい、私は今必要な編集を行いました。私はちょうど本当の質問をあまりにも多くの詳細があいまいになる反対の問題を避けようとしました。簡潔さと複雑さの間の適切なバランスを見つけることは、真の技​​術です。 – Alex

1

CancelationTokenSourceを使用してください。 5秒後にタスクが自動的にキャンセルされます。

var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(5000)); 

await ForeverRunningTaskAsync(cts.Token).ConfigureAwait(false); 
関連する問題