ちょうどVS2012を手に入れ、ハンドルを取得しようとしていますasync
。
ブロッキングソースから値をフェッチするメソッドがあるとします。メソッドの呼び出し元をブロックしたくありません。値が到着したときに呼び出されるコールバックを受け取るメソッドを作成することもできますが、C#5を使用しているため、メソッドを非同期にして、呼び出し側がコールバックを処理する必要がないようにします。
// contrived example (edited in response to Servy's comment)
public static Task<string> PromptForStringAsync(string prompt)
{
return Task.Factory.StartNew(() => {
Console.Write(prompt);
return Console.ReadLine();
});
}
これを呼び出すメソッドの例を次に示します。PromptForStringAsync
非同期でない場合、このメソッドはコールバック内にコールバックをネストする必要があります。asyncを使用すると、非常に自然な方法でメソッドを記述できます。
public static async Task GetNameAsync()
{
string firstname = await PromptForStringAsync("Enter your first name: ");
Console.WriteLine("Welcome {0}.", firstname);
string lastname = await PromptForStringAsync("Enter your last name: ");
Console.WriteLine("Name saved as '{0} {1}'.", firstname, lastname);
}
ここまでは順調ですね。問題は、GetNameAsync を呼び出すときです。
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
全体のポイントGetNameAsync
は、非同期であることです。欲しくないMainWorkOfApplicationIDontWantBlocked ASAPに戻り、GetNameAsyncにバックグラウンドで処理させので、ブロックし。ただし、この方法で呼び出すと、次のGetNameAsync
行にコンパイラの警告が表示されます。
Warning 1 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
「現在のメソッドの実行は、呼び出しが完了する前に続行される」ことを完全に認識しています。それはポイントですが非同期コードですよね?
警告なしでコードをコンパイルすることを好みますが、コードが意図したとおりに動作しているため、ここで「修正」することは何もありません。の戻り値を格納することで警告を取り除くことができますGetNameAsync
:
public static void DoStuff()
{
var result = GetNameAsync(); // supress warning
MainWorkOfApplicationIDontWantBlocked();
}
しかし、今は余分なコードがあります。Visual Studioは、私がこの不要なコードを書くことを余儀なくされたことを理解しているようです。これは、通常の「値が使用されない」という警告が抑制されるためです。
GetNameAsyncを非同期ではないメソッドでラップすることにより、警告を取り除くこともできます。
public static Task GetNameWrapper()
{
return GetNameAsync();
}
しかし、それはそれ以上です余分なコードです。そのため、不要な警告を許容しない、または許容しないコードを記述する必要があります。
ここで間違っている非同期の使用について何かありますか?
GetNameAsync
、すなわち(ユーザーによって提供されたフルネーム提供するためにTask<Name>
、というだけで返すよりもTask
? DoStuff
そのタスクを格納することができ、そしてどちらかawait
それをした後、他の方法、あるいはそのほかにタスクを渡すをメソッドを実装できるようにするawait
かWait
、実装内のどこかに
async
キーワードを削除してください。
PromptForStringAsync
するときは、必要以上の作業を行います。の結果を返すだけですTask.Factory.StartNew
。既にタスクであり、その値はコンソールに入力された文字列です。結果を返すまで待つ必要はありません。そうしても新しい価値はありません。