我如何等到任务在C#中完成?

我想向服务器发送请求并处理返回的值:

private static string Send(int id) { Task 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 httpTask) { Task 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; } 

我正确使用Task吗? 我不这么认为,因为Send()方法每次都返回string.Empty ,而Print返回正确的值。

我究竟做错了什么? 如何从服务器获得正确的结果?

您的Print方法可能需要等待继续完成(ContinueWith返回您可以等待的任务)。 否则,第二个ReadAsStringAsync结束,方法返回(在继续中分配结果之前)。 您的send方法中存在同样的问题。 两者都需要等待延续才能始终如一地获得所需的结果。 类似于下面

 private static string Send(int id) { Task 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 httpTask) { Task 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; } 

它等待client.GetAsync("aaaaa"); ,但不等待result = Print(x)

尝试responseTask.ContinueWith(x => result = Print(x)).Wait()

– 编辑 –

 Task responseTask = Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("In task"); }); responseTask.ContinueWith(t=>Console.WriteLine("In ContinueWith")); responseTask.Wait(); Console.WriteLine("End"); 

以上代码不保证输出:

 In task In ContinueWith End 

但这样做(参见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"); 

我是一个异步的新手,所以我无法明确告诉你这里发生了什么。 我怀疑方法执行期望存在不匹配,即使您在方法内部使用任务。 如果您更改Print以返回Task ,我想您会得到您期望的结果:

 private static string Send(int id) { Task responseTask = client.GetAsync("aaaaa"); Task 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 Print(Task httpTask) { Task task = httpTask.Result.Content.ReadAsStringAsync(); string result = string.Empty; task.ContinueWith(t => { Console.WriteLine("Result: " + t.Result); result = t.Result; }); return task; } 

在使用continuation时,我发现想到我写的地方很有用.ContinueWith作为执行立即继续执行它后面的语句的地方,而不是语句’inside’。 在这种情况下,很明显你会在Send中返回一个空字符串。 如果您对响应的唯一处理是将其写入控制台,则不需要任何Wait in Ito的解决方案 – 控制台打印输出将无需等待,但在这种情况下,发送和打印都应返回无效。 在控制台应用程序中运行此命令,您将获得页面的打印输出。

有时需要IMO,等待和Task.Result调用(哪个块),具体取决于您所需的控制流,但更常见的是它们表明您并未真正正确使用异步function。

 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 responseTask = client.GetAsync("http://google.com"); responseTask.ContinueWith(x => Print(x)); } private static void Print(Task httpTask) { Task task = httpTask.Result.Content.ReadAsStringAsync(); Task continuation = task.ContinueWith(t => { Console.WriteLine("Result: " + t.Result); }); } } } 
 async Task AccessTheWebAsync() { // You need to add a reference to System.Net.Http to declare client. HttpClient client = new HttpClient(); // GetStringAsync returns a Task. That means that when you await the // task you'll get a string (urlContents). Task 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; } 

回答标题的一个干净的例子

 string output = "Error"; Task task = Task.Factory.StartNew(() => { System.Threading.Thread.Sleep(2000); output = "Complete"; }); task.Wait(); Console.WriteLine(output);