c# - ReadToEndAsync 是阻塞的,如何让它异步运行?

标签 c# .net asp.net-mvc stream

我从 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 之后的代码执行,直到该方法完成。这正是您想要的:您不希望该代码在读取完成之前执行,否则它不会有可操作的结果。

您可能应该(重新?)阅读有关 asyncawait 的文档,但简单地说:关键字 async 应用于一个方法,向编译器发出信号,表明它将使用 awaitawait 用于向编译器指示方法中的一个点,编译器应在该点保存方法的当前执行状态并返回

如果应用了 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/

相关文章:

asp.net-mvc - 使用 Ninject 设置服务

c# - ASP.NET vNext 和 EF7 中的多个 dbContext

c# - XmlElement 到字符串的转换

c# - 测试一个类是否可以被序列化

c# - 无法使用 Autofac 解析 NameValueCollection

.NET Core SDK 与 Docker 的运行时版本

.net - Linq to objects 查找索引和求和结果

.net - 设置每个操作的 MaxAllowedContentLength/maxRequestLength 值

ASP.Net MVC - 从代码隐藏生成 ActionLink?

c# - 如何在c#.net中的多线程和每行一个线程中逐行处理文件?