C#async HttpWebRequest死锁

时间:2016-01-13 00:05:51

标签: c# asynchronous async-await httpwebrequest

几个小时后,我在C#中遇到异步代码,我无法理解为什么我的代码陷入僵局。 到目前为止,我已经发了许多文章,并为我敲响了任何东西。

希望你能帮助我。

这是我试图运行的代码。

主要

    Task.Run(async () =>
    {
        Task<EventDetailed[]> events = getDetailedEvents();
        await events;
    }).Wait();

getDetailedEvents:

 static async Task<EventDetailed[]> getDetailedEvents()
        {
            ...
            EventDetailed[] result = await LoadDetailedEventsDetailsAsync(evnts).ConfigureAwait(false);

            return result;
        }

我问题的核心。

LoadDetailedEventsDetailsAsync

async static Task<EventDetailed[]> LoadDetailedEventsDetailsAsync(Event[] events)
        {
            List<EventDetailed> detailed = new List<EventDetailed>();
            List<Task<WebResponse>> responses = new List<Task<WebResponse>>();
            List<Event> tasksWithStream = new List<Event>();
            foreach (Event e in events)
            {
                var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://...");
                ... some headers etc ... 
                e.Stream = httpWebRequest.GetRequestStreamAsync();
                e.WebRequest = httpWebRequest;
                tasksWithStream.Add(e);
            }
            foreach (var tsk in tasksWithStream)
            { 

                try {
                    await tsk.Stream.ConfigureAwait(false);
                    using (var streamWriter = new StreamWriter(tsk.Stream.Result))
                    {
                        streamWriter.Write("...");
                        streamWriter.Flush();
                        streamWriter.Close();
                    }
                    responses.Add(tsk.WebRequest.GetResponseAsync());
                }
                catch (Exception ex)
                {
                    Logger.mes("Failed to get event data.");
                }
            }
            foreach (var response in responses)
            {
                try
                {
                    await response.ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.mes("Failed to get event data.");
                    continue;
                }
                parseData.Add(ParseData(response));
            }

1 个答案:

答案 0 :(得分:1)

几点:

首先,重要的是要注意你应该几乎永远不会在异步任务上调用.Wait(或.Result) - 你应该使用{{1相反。其中一个非常的例外情况是在控制台应用的await方法中。原因是如果你不阻止主线程,你的程序就会过早退出。

其次,如果您需要发出多个不相互依赖的HTTP请求(即请求B不需要请求A的结果),那么通过并行执行它们可以获得巨大的性能提升。更好的是,您不会为每个请求消耗一个线程,因为调用是异步的,即它们在等待响应时不会阻塞线程,因此同一个线程可以有效地触发许多并发请求。

我不会重新编写您的代码,但我会建议我如何对其进行重组:

Main
相关问题