Comment puis-je attendre que la tâche soit terminée en C#?
je veux envoyer une requête à un serveur et des processus la valeur retournée:
private static string Send(int id)
{
Task<HttpResponseMessage> responseTask = client.GetAsync("aaaaa");
string result = string.Empty;
responseTask.ContinueWith(x => result = Print(x));
responseTask.Wait(); // it doesn't wait for the completion of the response task
return result;
}
private static string Print(Task<HttpResponseMessage> httpTask)
{
Task<string> task = httpTask.Result.Content.ReadAsStringAsync();
string result = string.Empty;
task.ContinueWith(t =>
{
Console.WriteLine("Result: " + t.Result);
result = t.Result;
});
task.Wait(); // it does wait
return result;
}
Est - ce que j'utilise Task
correctement? Je ne le pense pas, parce que le Send()
retourne la méthode string.Empty
tous les temps, tandis que Print
renvoie la valeur correcte.
Qu'est-ce que je fais de mal? Comment obtenir le bon résultat d'un serveur?
6 réponses
votre méthode D'impression a probablement besoin d'attendre la fin de la suite (ContinueWith renvoie une tâche que vous pouvez attendre). Sinon le deuxième ReadAsStringAsync finit, la méthode retourne (avant que le résultat soit assigné dans la suite). Même problème existe dans votre méthode d'envoi. Les deux ont besoin d'attendre la suite pour obtenir systématiquement les résultats que vous voulez. Semblable à ci-dessous
private static string Send(int id)
{
Task<HttpResponseMessage> responseTask = client.GetAsync("aaaaa");
string result = string.Empty;
Task continuation = responseTask.ContinueWith(x => result = Print(x));
continuation.Wait();
return result;
}
private static string Print(Task<HttpResponseMessage> httpTask)
{
Task<string> task = httpTask.Result.Content.ReadAsStringAsync();
string result = string.Empty;
Task continuation = task.ContinueWith(t =>
{
Console.WriteLine("Result: " + t.Result);
result = t.Result;
});
continuation.Wait();
return result;
}
Il attend client.GetAsync("aaaaa");
, mais ne pas attendre result = Print(x)
responseTask.ContinueWith(x => result = Print(x)).Wait()
--EDIT--
Task responseTask = Task.Run(() => {
Thread.Sleep(1000);
Console.WriteLine("In task");
});
responseTask.ContinueWith(t=>Console.WriteLine("In ContinueWith"));
responseTask.Wait();
Console.WriteLine("End");
code ci-Dessus n'est pas garantie de la sortie:
In task
In ContinueWith
End
mais c'est le cas (voir newTask
)
Task responseTask = Task.Run(() => {
Thread.Sleep(1000);
Console.WriteLine("In task");
});
Task newTask = responseTask.ContinueWith(t=>Console.WriteLine("In ContinueWith"));
newTask.Wait();
Console.WriteLine("End");
je suis un novice async, donc je ne peux pas vous dire définitivement ce qui se passe ici. Je soupçonne qu'il y a une inadéquation dans les attentes d'exécution de la méthode, même si vous utilisez des tâches en interne dans les méthodes. Je pense que vous obtiendriez les résultats que vous attendez si vous changez L'impression pour retourner une tâche
private static string Send(int id)
{
Task<HttpResponseMessage> responseTask = client.GetAsync("aaaaa");
Task<string> result;
responseTask.ContinueWith(x => result = Print(x));
result.Wait();
responseTask.Wait(); // There's likely a better way to wait for both tasks without doing it in this awkward, consecutive way.
return result.Result;
}
private static Task<string> Print(Task<HttpResponseMessage> httpTask)
{
Task<string> task = httpTask.Result.Content.ReadAsStringAsync();
string result = string.Empty;
task.ContinueWith(t =>
{
Console.WriteLine("Result: " + t.Result);
result = t.Result;
});
return task;
}
en travaillant avec des continuations je trouve utile de penser à l'endroit où j'écris .Continue comme le lieu à partir duquel l'exécution continue immédiatement aux déclarations qui la suivent, pas les déclarations "à l'intérieur" elle. Dans ce cas, il devient évident que vous obtenez une chaîne vide est retournée en Envoyer. Si votre seul traitement de la réponse est de l'écrire à la console, vous n'avez pas besoin d'attendre dans la solution D'Ito - l'impression de la console se fera sans attendre mais à la fois Envoyer et imprimer doit retourner nulle dans ce cas. Exécutez cette application console et vous aurez l'impression de la page.
l'OMI, de l'attente et de la Tâche.Les appels de résultat (quel bloc) sont parfois nécessaires, en fonction de votre débit de contrôle désiré, mais le plus souvent ils sont un signe que vous n'utilisez pas vraiment la fonctionnalité asynchrone correctement.
namespace TaskTest
{
class Program
{
static void Main(string[] args)
{
Send();
Console.WriteLine("Press Enter to exit");
Console.ReadLine();
}
private static void Send()
{
HttpClient client = new HttpClient();
Task<HttpResponseMessage> responseTask = client.GetAsync("http://google.com");
responseTask.ContinueWith(x => Print(x));
}
private static void Print(Task<HttpResponseMessage> httpTask)
{
Task<string> task = httpTask.Result.Content.ReadAsStringAsync();
Task continuation = task.ContinueWith(t =>
{
Console.WriteLine("Result: " + t.Result);
});
}
}
}
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask =
client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from
getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebenter code hereAsync retrieve the length
value.
return urlContents.Length;
}
un exemple propre qui répond au titre
string output = "Error";
Task task = Task.Factory.StartNew(() =>
{
System.Threading.Thread.Sleep(2000);
output = "Complete";
});
task.Wait();
Console.WriteLine(output);