Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#异步HttpWebRequest死锁_C#_Asynchronous_Async Await_Httpwebrequest - Fatal编程技术网

C#异步HttpWebRequest死锁

C#异步HttpWebRequest死锁,c#,asynchronous,async-await,httpwebrequest,C#,Asynchronous,Async Await,Httpwebrequest,几个小时以来,我一直在努力处理C#中的异步代码,我真的不明白为什么我的代码会死锁。 到目前为止,我已经写了很多文章,任何事情都让我感到震惊 希望你能帮助我 下面是我试图运行的代码 主要 Task.Run(异步()=> { 任务事件=getDetailedEvents(); 等待事件发生; }).Wait(); getDetailedEvents: static async Task<EventDetailed[]> getDetailedEvents() {

几个小时以来,我一直在努力处理C#中的异步代码,我真的不明白为什么我的代码会死锁。 到目前为止,我已经写了很多文章,任何事情都让我感到震惊

希望你能帮助我

下面是我试图运行的代码

主要

Task.Run(异步()=>
{
任务事件=getDetailedEvents();
等待事件发生;
}).Wait();
getDetailedEvents:

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

            return result;
        }
静态异步任务getDetailedEvents()
{
...
EventDetailed[]结果=等待LoadDetailedEventsDetailsSync(evnts)。配置等待(false);
返回结果;
}
也是我问题的核心

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));
            }
异步静态任务LoadDetailedEventsDetailsAsync(事件[]事件)
{
详细列表=新列表();
列表响应=新列表();
List tasksWithStream=new List();
foreach(事件中的事件e)
{
var httpWebRequest=(httpWebRequest)WebRequest.Create(“http://...");
…一些标题等。。。
e、 Stream=httpWebRequest.GetRequestStreamAsync();
e、 WebRequest=httpWebRequest;
tasksWithStream.Add(e);
}
foreach(tasksWithStream中的var tsk)
{ 
试一试{
wait tsk.Stream.configurewait(false);
使用(var streamWriter=newstreamwriter(tsk.Stream.Result))
{
streamWriter.Write(“…”);
streamWriter.Flush();
streamWriter.Close();
}
Add(tsk.WebRequest.GetResponseAsync());
}
捕获(例外情况除外)
{
Logger.mes(“未能获取事件数据”);
}
}
foreach(响应中的var响应)
{
尝试
{
等待响应。配置等待(false);
}
捕获(例外情况除外)
{
Logger.mes(“未能获取事件数据”);
继续;
}
Add(parseData(response));
}
几点:

首先,需要注意的是,您几乎不应该调用
.Wait
(或
.Result
)在异步任务上-您应该使用
wait
。控制台应用程序的
Main
方法是极少数例外情况之一。原因是如果不阻止主线程,您的程序将过早退出

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

我不会重新编写您的代码,但我会建议如何重构它:

static void Main(string[] args)
{
    // start all async tasks in parallel.
    var tasks = GetEvents().Select(GetEventDetailsAsync);

    // wait for them all to complete. normally you should use await instead of Wait,
    // but you can't because you're in the main method of a console app.
    Task.WhenAll(task).Wait();
}

static IEnumerable<Event> GetEvents()
{
    // build a list of whatever metadata is needed to do your async work.
    // do NOT do any actual async work here.
}

async static Task<EventDetailed> GetEventDetailsAsync(Event e)
{
    // do all async work here, use await as needed,
    // but only for one event (no loops).
}
static void Main(字符串[]args)
{
//并行启动所有异步任务。
var tasks=GetEvents().Select(GetEventDetailsAsync);
//等待它们全部完成。通常你应该使用wait而不是wait,
//但你不能,因为你是在一个控制台应用程序的主要方法。
Task.WhenAll(Task.Wait();
}
静态IEnumerable GetEvents()
{
//建立一个列表,列出异步工作所需的元数据。
//不要在这里做任何实际的异步工作。
}
异步静态任务GetEventDetailsAsync(事件e)
{
//在此处执行所有异步工作,根据需要使用wait,
//但仅针对一个事件(无循环)。
}

它是什么类型的应用程序?控制台应用程序?WPF?Windows窗体?事件类是什么样的?具体来说,
事件流的定义是什么?
?不要
等待
getDetailedEvents
上。因为你在状态机上调用
等待
,它会死锁。@YacoubMassad:it i声明是公共任务流{get;set;}@FilipEkberg:听起来不错,我会尽快试用!希望到时候我能理解为什么这段代码会死锁。顺便说一句,您建议在第一次调用中删除wait并只使用其结果?
static void Main(string[] args)
{
    // start all async tasks in parallel.
    var tasks = GetEvents().Select(GetEventDetailsAsync);

    // wait for them all to complete. normally you should use await instead of Wait,
    // but you can't because you're in the main method of a console app.
    Task.WhenAll(task).Wait();
}

static IEnumerable<Event> GetEvents()
{
    // build a list of whatever metadata is needed to do your async work.
    // do NOT do any actual async work here.
}

async static Task<EventDetailed> GetEventDetailsAsync(Event e)
{
    // do all async work here, use await as needed,
    // but only for one event (no loops).
}