ReadToEndAsync 正在阻塞,如何异步获取它到 运行?
ReadToEndAsync is blocking, how to get it to run asynchronously?
我从控制器中的异步操作调用此 getJson() 函数。
我有一个大文件列表,每个文件都需要几秒钟的时间供 ReadToEndAsync() 处理。
ReadToEndAsync() 正在阻塞,即使我正在等待它。
如何异步调用 ReadToEndAsync()?
public static async Task<T> getJson<T>(String url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(server + url);
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
String jsonString;
//get the json string from the response
using (var xx = response.GetResponseStream())
{
StreamReader reader = new StreamReader(xx, Encoding.UTF8);
jsonString = await reader.ReadToEndAsync()
}
}
控制器:
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
如评论中所述,虽然方法 ReadToEndAsync()
确实 而不是 块本身——在词的通常意义上 "block":即,调用该方法的线程继续 运行——它肯定会阻止 await
之后的代码执行,直到该方法完成。这正是您想要的:您不希望该代码在读取完成之前执行,否则它不会有可操作的结果。
您可能应该(重新?)阅读有关 async
和 await
的文档,但简而言之:关键字 async
应用于方法以向编译器发出信号将使用 await
。 await
用于向编译器指示方法中的一个点,编译器应在该点保存方法的当前执行状态 和 return.
如果应用了 await
关键字的操作完成,框架将自动继续执行它停止的方法。在绑定到同步上下文的线程中调用该方法的地方(例如 Winforms 或 WPF 程序中的 GUI 线程),默认情况下此 "continuation" 在该原始线程中执行(但可以在适当的时候禁用它).
请注意上面的 async
方法 returns 来自 await
语句。因此,该方法本身不会阻塞线程,即使该方法表示的操作在某种意义上确实 "block"。
因此,综上所述,在我看来,您可能正在尝试让您的三个操作全部异步并发完成。如果你想这样做,你需要立即启动所有异步操作,而不是像现在一样等待每个操作完成后再继续下一个操作(即通过应用于调用的 await
语句) getJason<T>()
方法)。
看起来像这样:
Task<ReviewModel> task1 = DataRetriever.getJson<ReviewModel>(url1),
task2 = DataRetriever.getJson<ReviewModel>(url2),
task3 = DataRetriever.getJson<ReviewModel>(url3);
_model.list.Add(await task1);
_model.list.Add(await task2);
_model.list.Add(await task3);
(注意:在您的原始代码示例中,您只使用了一个 url
值。因为我假设您真的不想只在不同的时间执行相同的查询三次,所以我继续进行更改代码示例,以便每个任务使用不同的值)。
在上面,即使第二个and/or第三个任务先于第一个任务完成,结果也会按顺序添加到结果列表中。 但是任务本身是同时启动的,因此它们可以运行并发。
我希望以上内容不仅能为您阐明对方法 ReadToEndAsync()
的调用是否阻塞(它不会,尽管由于调试器呈现代码执行的方式,它可能 seem 它确实如此),但也为您提供了解决导致您调试该方法的更大问题的方法,认为 它正在阻塞。 IE。您的 JSON 查询没有同时执行。
如果在对您的问题发表评论和上面的回答之间,您仍然遇到问题,请编辑您的问题,以便更清楚地了解您到底在问什么。
我从控制器中的异步操作调用此 getJson() 函数。 我有一个大文件列表,每个文件都需要几秒钟的时间供 ReadToEndAsync() 处理。 ReadToEndAsync() 正在阻塞,即使我正在等待它。
如何异步调用 ReadToEndAsync()?
public static async Task<T> getJson<T>(String url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(server + url);
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
String jsonString;
//get the json string from the response
using (var xx = response.GetResponseStream())
{
StreamReader reader = new StreamReader(xx, Encoding.UTF8);
jsonString = await reader.ReadToEndAsync()
}
}
控制器:
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
如评论中所述,虽然方法 ReadToEndAsync()
确实 而不是 块本身——在词的通常意义上 "block":即,调用该方法的线程继续 运行——它肯定会阻止 await
之后的代码执行,直到该方法完成。这正是您想要的:您不希望该代码在读取完成之前执行,否则它不会有可操作的结果。
您可能应该(重新?)阅读有关 async
和 await
的文档,但简而言之:关键字 async
应用于方法以向编译器发出信号将使用 await
。 await
用于向编译器指示方法中的一个点,编译器应在该点保存方法的当前执行状态 和 return.
如果应用了 await
关键字的操作完成,框架将自动继续执行它停止的方法。在绑定到同步上下文的线程中调用该方法的地方(例如 Winforms 或 WPF 程序中的 GUI 线程),默认情况下此 "continuation" 在该原始线程中执行(但可以在适当的时候禁用它).
请注意上面的 async
方法 returns 来自 await
语句。因此,该方法本身不会阻塞线程,即使该方法表示的操作在某种意义上确实 "block"。
因此,综上所述,在我看来,您可能正在尝试让您的三个操作全部异步并发完成。如果你想这样做,你需要立即启动所有异步操作,而不是像现在一样等待每个操作完成后再继续下一个操作(即通过应用于调用的 await
语句) getJason<T>()
方法)。
看起来像这样:
Task<ReviewModel> task1 = DataRetriever.getJson<ReviewModel>(url1),
task2 = DataRetriever.getJson<ReviewModel>(url2),
task3 = DataRetriever.getJson<ReviewModel>(url3);
_model.list.Add(await task1);
_model.list.Add(await task2);
_model.list.Add(await task3);
(注意:在您的原始代码示例中,您只使用了一个 url
值。因为我假设您真的不想只在不同的时间执行相同的查询三次,所以我继续进行更改代码示例,以便每个任务使用不同的值)。
在上面,即使第二个and/or第三个任务先于第一个任务完成,结果也会按顺序添加到结果列表中。 但是任务本身是同时启动的,因此它们可以运行并发。
我希望以上内容不仅能为您阐明对方法 ReadToEndAsync()
的调用是否阻塞(它不会,尽管由于调试器呈现代码执行的方式,它可能 seem 它确实如此),但也为您提供了解决导致您调试该方法的更大问题的方法,认为 它正在阻塞。 IE。您的 JSON 查询没有同时执行。
如果在对您的问题发表评论和上面的回答之间,您仍然遇到问题,请编辑您的问题,以便更清楚地了解您到底在问什么。