2017-09-14 3 views
0

私は基本クラスから継承するコマンドのグループを持っています。async待機する必要のないタスクメソッド

public virtual async Task Execute(object parameter){} 

継承クラスはこのメソッドのオーバーライドを提供し、すべてがタスクを待っているわけではありません。このような場合、コンパイラは警告を生成します。

この非同期メソッドには 'await'演算子がなく、同期して実行されます。 'await'演算子を使用して、ノンブロッキングAPI呼び出し、 または 'await Task.Run(...)'を待機し、バックグラウンドスレッドでCPUバインド処理を行うことを検討してください。

タスクに完全な戻り値を明示的に指定するのは正しいですか?

public override async Task Execute(object parameter) { 
    //code containing no await statements... 
    await Task.CompletedTask; 
} 

答えて

5

あなたは何にもないawaitを行うオーバーライドされたメソッドの内部asyncキーワードの使用を避け、代わりにちょうどTask.CompletedTaskを返す必要があります:

public override Task Execute(object parameter) { 
    //code containing no await statements... 
    return Task.CompletedTask; // or Task.FromResult(0) for older .NET versions 
} 

これは(少数)の一つであるがための例を使用しますあなたが理解できるように、looking at this questionTask.FromResultのような "嘲笑された"タスク。これらの考慮事項はTask.CompletedTaskでも有効です。

+2

私は差分を取っ私の元のコードの出力と推奨される変更の出力はdotPeekから得られ、それらは同じです(デバッグDLL)。あなたの例は私の元々の動機であったコンパイラの警告も削除します。 - ありがとう! – jchristof

3

対称として、であり、例外の処理方法の違いがあります。

asyncバージョンの同期コードから例外が発生した場合、その例外は呼び出し元に直接送信されます(非同期シグネチャを持つメソッドでは非常に珍しい)。

asyncバージョンの同期コードから例外が発生した場合、その例外が取得され、返されたタスクに配置されます(これは非同期シグネチャを持つメソッドの予想される動作です)。

方法がなどと呼ばれているのであれば、異なる実装が異なる例外セマンティクスを持っているでしょう:

var task = Execute(parameter); // non-async exceptions raised here 
... 
await task; // async exceptions raised here 

時間のほとんどは、しかし、メソッドが呼び出されるとすぐに待望ので、これら二つの意味がマージされます一緒:

await Execute(parameter); // both async and non-async exceptions raised here 

それはおそらくは問題ではないだろうが、私はそれが知っておくべき重要な違いだと信じています。

例外セマンティクスがあなたにとって重要である場合、あなたはがあなたの同期コードの周りにステートマシンを生成するためにasyncを使いたいん、そして、あなたのコード内の警告を無効にすることができます

#pragma warning disable 1998 // use async keyword to capture exceptions 
public override async Task Execute(object parameter) { 
#pragma warning restore 1998 
    //code containing no await statements... 
} 
関連する問題