web-dev-qa-db-ja.com

Task <int>はどのようにintになりますか?

このメソッドがあります:

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

   Task<string> getStringTask = client.GetStringAsync("http://msdn.Microsoft.com");

   // You can do work here that doesn't rely on the string from GetStringAsync.
   DoIndependentWork();

   string urlContents = await getStringTask;
   //The thing is that this returns an int to a method that has a return type of Task<int>
   return urlContents.Length;
}

Task<int>intの間で暗黙的な変換が発生しますか?そうでない場合、何が起こっていますか?どのように動作するように実装されていますか?

98
Freeman

Task <>とintの間で暗黙的な変換が発生しますか?

いや。これは、async/awaitの機能の一部にすぎません。

asyncとして宣言されたメソッドには、戻り値の型が必要です。

  • void(可能であれば避ける)
  • Task(完了/失敗の通知を超える結果はありません)
  • Task<T>(非同期的な方法でのT型の論理結果用)

コンパイラーはすべての適切なラッピングを行います。ポイントは、あなたが非同期urlContents.Lengthを返すことです-実際のメソッドは最初のint式にヒットしたときに戻るため、メソッドがawaitを返すようにすることはできませんもう完成された。その代わり、非同期メソッド自体が完了すると完了するTask<int>を返します。

awaitは逆のことを行うことに注意してください-it nwraps a Task<T>T値に変換します。

string urlContents = await getStringTask;

...もちろん、非同期にラップを解除しますが、Resultを使用するとタスクが完了するまでブロックされます。 (awaitは、awaitableパターンを実装する他の型をアンラップできますが、Task<T>が最も頻繁に使用される可能性があります。)

この二重ラッピング/アンラッピングは、非同期を非常に構成可能にするものです。たとえば、あなたのものを呼び出して結果を2倍にする別の非同期メソッドを書くことができます:

public async Task<int> AccessTheWebAndDoubleAsync()
{
    var task = AccessTheWebAsync();
    int result = await task;
    return result * 2;
}

(または単にreturn await AccessTheWebAsync() * 2;もちろん。)

146
Jon Skeet

いいえ、タスクをintに変換する必要はありません。タスク結果を使用するだけです。

int taskResult = AccessTheWebAndDouble().Result;

public async Task<int> AccessTheWebAndDouble()
{
    int task = AccessTheWeb();
    return task;
}

可能な場合は値を返し、そうでない場合は0を返します。

11
Aniket Sharma