在开发一个需要从远程服务器下载数据并解析的应用程序中,你可能会使用到 HttpClient 来发起HTTP请求,并使用 Task 来异步处理这些请求。在处理完数据并准备输出结果时,你是否也曾像我的代码示例一样,错误地使用了 Task 来封装 Console.WriteLine 呢?
这是我的一个不正确的写法:
//class Program
//{
// static async Task Main(string[] args)
// {
// string url = "https://www.msn.cn/zh-cn/feed?ocid=msedgntp&pc=U531&cvid=6681676bd37c4a03b9cc1e52e7c80b59&ei=10";
// Task<HttpResponseMessage> downloadTask = Task.Run(async () =>
// {
// using (var client = new HttpClient()) { return await client.GetAsync(url); }
// });
// // 使用ContinueWith来创建一个新任务,这个任务在downloadTask完成后执行
// Task<string> parseTask = downloadTask.ContinueWith(async (t1) =>
// {
// if (t1.Status == TaskStatus.RanToCompletion)
// {
// var response = t1.Result;
// if (response.IsSuccessStatusCode)
// { string data = await response.Content.ReadAsStringAsync(); return "解析后的数据: " + data; }
// else
// { return "请求失败,状态码: " + response.StatusCode; }
// }
// else { return "下载任务失败"; }
// });
// // 使用ContinueWith来创建最终的任务,这个任务在parseTask完成后执行
// Task outputTask = parseTask.ContinueWith(t2 =>
// { Console.WriteLine(t2.Result); });
// await outputTask;
// }
//}
在zhege代码中,outputTask 使用 Task 来封装 Console.WriteLine 是不必要的,因为 Console.WriteLine 本身是同步的,不会执行任何异步操作。可以直接在 parseTask 的 ContinueWith 回调中调用 Console.WriteLine,从而简化代码。
修改后的代码为:
、、、、/////前面不变
// 直接使用ContinueWith,并在其中直接调用Console.WriteLine
downloadTask.ContinueWith(async (t1) =>
{
if (t1.Status == TaskStatus.RanToCompletion)
{
var response = t1.Result;
if (response.IsSuccessStatusCode)
{
string data = await response.Content.ReadAsStringAsync();
Console.WriteLine("解析后的数据: " + data); // 直接输出
}
else
{
Console.WriteLine("请求失败,状态码: " + response.StatusCode);
}
}
else
{
Console.WriteLine("下载任务失败");
}
}).Wait(); // 等待整个操作完成
进行优化后,通过直接使用 ContinueWith 并在回调中调用 Console.WriteLine,简化了代码结构,提高了代码的可读性和可维护性。同时,这也避免了不必要的 Task 封装,提高了程序的执行效率。
希望本文对你有所帮助!