web-dev-qa-db-fra.com

Comment Task <int> devient-il un int?

Nous avons cette méthode:

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;
}

Une conversion implicite a-t-elle lieu entre Task<int> et int? Si non, alors qu'est-ce qui se passe? Comment est-il implémenté pour fonctionner?

98
Freeman

Une conversion implicite a-t-elle lieu entre Task <> et int?

Nan. Cela fait partie du fonctionnement de async/await.

Toute méthode déclarée comme async doit avoir un type de retour de:

  • void (à éviter si possible)
  • Task (pas de résultat après la notification d'achèvement/d'échec)
  • Task<T> (Pour un résultat logique de type T de manière asynchrone)

Le compilateur effectue tout le wrapping approprié. Le fait est que vous êtes asynchrone retournant urlContents.Length - vous ne pouvez pas faire en sorte que la méthode retourne simplement int, car la méthode actuelle retournera dès qu'elle aura atteint le premier await expression qui n'est pas encore terminée. Au lieu de cela, il retourne un Task<int> Qui se terminera à la fin de la méthode asynchrone.

Notez que await fait le contraire - il décompresse un Task<T> À une valeur T, qui est le fonctionnement de cette ligne:

string urlContents = await getStringTask;

... mais bien sûr, il le décompresse de manière asynchrone, alors que le simple fait d'utiliser Result bloquerait jusqu'à ce que la tâche soit terminée. (await peut décompresser les autres types qui implémentent le modèle attendu, mais Task<T> est celui que vous utiliserez le plus souvent.)

C'est ce double emballage qui permet à async d'être si facilement composables. Par exemple, je pourrais écrire une autre méthode asynchrone qui appelle la vôtre et double le résultat:

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

(Ou simplement return await AccessTheWebAsync() * 2; bien sûr.)

146
Jon Skeet

Non nécessite la conversion de la tâche en int. Utilisez simplement le résultat de la tâche.

int taskResult = AccessTheWebAndDouble().Result;

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

Il retournera la valeur si disponible sinon il retournera 0.

11
Aniket Sharma