10

たとえば、何かを待機するたびに、コンパイラは、含まれているメソッドが Async でなければならないことを通知します。非同期ランバがこのように表示されないのはなぜですか? ForEach がそれを隠している場合、Task オブジェクトを返さず、ForEach が暗黙的に async void であることに関して何らかの危険がありますか?

public void SaveSome()
{
    Array.ForEach(Enumerable.Range(0,3).ToArray(), async x =>  await SaveRep());
}
4

2 に答える 2

12

非同期ラムダは、非同期のデリゲートを作成する簡単な方法です。それを含むメソッドは、それ自体で非同期に何かawaitをしなければならないということは何もありません - そして、ラムダ式内の式は、含まれているメソッドを待機させません (もちろん、たまたまデリゲートに依存するタスクを待っている場合を除きます)。 .

基本的に、ラムダ式は非同期コードを表現しています。非同期コード自体を実行しているわけではありません...したがって、含まれているメソッドは必ずしも非同期で実行されているわけではありません。

はい、あなたが示した例は非同期ラムダの誤用ですが、メソッドを非同期にしても問題はまったく改善されず、単に誤解を招くだけです。

EDIT:それについて考える別の方法として、元のコードのこのリファクタリングを検討してください:

public void SaveSome()
{
    Action<int> action = SaveRepAsync;
    Array.ForEach(Enumerable.Range(0,3).ToArray(), action);
}

private static async void SaveRepAsync(int x)
{
    await SaveRep();
}

SaveSomeメソッドにはそれについて非同期的なものは何もありません-メソッドだけがそうです...それが修飾子SaveRepAsyncを必要とするものです。asyncこれは実際にはコードの小さなリファクタリングにすぎません (コンパイラが効果的に行うリファクタリングのようなものです)。非同期ラムダを含むすべてのメソッドに async 修飾子を持たせたい場合、それは上記のコードでSaveSome修飾子も持つべきだと言っているようなものです...これは意味がありません、IMO.

于 2013-09-12T11:48:31.297 に答える