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

32 .net c# task wait task-parallel-library

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

Ken*_*Ito 31

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

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一下,你调用异步然后立即等待它的模式与同步调用几乎相同. (7认同)

L.B*_*L.B 6

它等待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");
Run Code Online (Sandbox Code Playgroud)

以上代码不保证输出:

In task
In ContinueWith
End
Run Code Online (Sandbox Code Playgroud)

但这样做(见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");
Run Code Online (Sandbox Code Playgroud)


vik*_*ian 6

一个回答标题的干净示例

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

task.Wait();
Console.WriteLine(output);
Run Code Online (Sandbox Code Playgroud)