我想向服务器发送请求并处理返回的值:
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;
}
我正确使用Task
吗?我不这么认为,因为Send()
方法每次都会返回string.Empty
,而Print
会返回正确的值。
我做错了什么?如何从服务器获得正确的结果?
答案 0 :(得分:29)
您的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;
}
答案 1 :(得分: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");
以上代码不保证输出:
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");
答案 2 :(得分:0)
我是一个异步的新手,所以我无法明确地告诉你这里发生了什么。我怀疑方法执行期望存在不匹配,即使您在方法内部使用任务。如果您更改了Print以返回任务&lt; string&gt;我认为您将得到您期望的结果:
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;
}
答案 3 :(得分:0)
当使用continuation时,我发现想到我写的地方很有用.ContinueWith作为执行立即继续执行它后面的语句的地方,而不是语句'inside'。在这种情况下,很明显你会在Send中返回一个空字符串。如果您对响应的唯一处理是将其写入控制台,则不需要任何Wait in Ito的解决方案 - 控制台打印输出将无需等待,但在这种情况下,发送和打印都应返回无效。在控制台应用程序中运行此命令,您将获得该页面的打印输出。
IMO,等待和Task.Result调用(哪个块)有时是必要的,这取决于你想要的控制流,但更多时候它们表明你并没有真正正确地使用异步功能。
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);
});
}
}
}
答案 4 :(得分:0)
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;
}
答案 5 :(得分:0)
一个简单的示例,回答标题
string output = "Error";
Task task = Task.Factory.StartNew(() =>
{
System.Threading.Thread.Sleep(2000);
output = "Complete";
});
task.Wait();
Console.WriteLine(output);