我从 Controller 中的异步操作调用此 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()
}
}
Controller :
_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()
本身不阻塞——在“阻塞”一词的通常意义上:也就是说,调用该方法的线程继续运行——它肯定会阻止 await
之后的代码执行,直到该方法完成。这正是您想要的:您不希望该代码在读取完成之前执行,否则它不会有可操作的结果。
您可能应该(重新?)阅读有关 async
和 await
的文档,但简单地说:关键字 async
应用于一个方法,向编译器发出信号,表明它将使用 await
。 await
用于向编译器指示方法中的一个点,编译器应在该点保存方法的当前执行状态并返回。
如果应用了 await
关键字的操作完成,框架将自动继续执行它停止的方法。如果在与同步上下文相关的线程(例如 Winforms 或 WPF 程序中的 GUI 线程)中调用该方法,则默认情况下此“延续”在原始线程中执行(但可以在适当时禁用此功能)。
请注意上面的 async
方法从 await
语句返回。因此,该方法本身不会阻塞线程,即使该方法表示的操作在某种意义上确实“阻塞”。
因此,综上所述,在我看来,您可能正在尝试让您的三个操作全部异步并发完成。如果您想这样做,则需要立即启动所有异步操作,而不是像现在一样等待每个操作完成后再继续下一个操作(即通过应用于对 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
值。由于我假设您并不真的想只执行相同的查询三次不同的时间,所以我继续更改了代码示例,以便每个任务使用不同的值)。
在上面,即使第二个和/或第三个任务在第一个任务之前完成,结果也会按顺序添加到结果列表中。 但是任务本身都是同时启动的,以便它们可以同时运行。
我希望上述内容不仅可以帮助您澄清对方法 ReadToEndAsync()
的调用是否被阻塞(实际上并没有,但由于调试器呈现代码执行的方式,它可能看起来它确实如此),而且还为您提供了更大问题的解决方案,导致您调试该方法并认为它正在阻塞。 IE。您的 JSON 查询没有同时执行。
如果在对您的问题的评论和上述答案之间,您仍然遇到问题,请编辑您的问题,以便更清楚地了解您到底在问什么。
关于c# - ReadToEndAsync 是阻塞的,如何让它异步运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28838050/