Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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# 调用EF异步方法时,异步任务冻结_C#_Entity Framework_Asynchronous - Fatal编程技术网

C# 调用EF异步方法时,异步任务冻结

C# 调用EF异步方法时,异步任务冻结,c#,entity-framework,asynchronous,C#,Entity Framework,Asynchronous,我有一个返回xml字符串的异步方法。当我将任务添加到任务列表中时,它会启动任务,但在使用实体框架与数据库对话时会挂起等待。下面是示例代码 public async Task<ActionResult> GenerateXml(long id) { var tasks = new List<Task<string>>(); tasks.Add(GenerateXmlAsync(id)); Task.WaitAll(tasks.ToArra

我有一个返回xml字符串的异步方法。当我将任务添加到任务列表中时,它会启动任务,但在使用实体框架与数据库对话时会挂起等待。下面是示例代码

public async Task<ActionResult> GenerateXml(long id)
{
    var tasks = new List<Task<string>>();
    tasks.Add(GenerateXmlAsync(id));
    Task.WaitAll(tasks.ToArray());
}

private async Task<string> GenerateXmlAsync(long id)
{
    using (var dbContext = new MyDatabaseContext())
    {
        var item = await dbContext.Items.FirstOrDefaultAsync(itm => itm.Id = id);
        /* do some calculations, generate the xml... */
        var xml = "<generated by code above>";
        return xml;
    }
}
公共异步任务GenerateXml(长id)
{
var tasks=新列表();
添加(GenerateXmlAsync(id));
Task.WaitAll(tasks.ToArray());
}
专用异步任务GenerateXmlAsync(长id)
{
使用(var dbContext=new MyDatabaseContext())
{
var item=await dbContext.Items.FirstOrDefaultAsync(itm=>itm.Id=Id);
/*做一些计算,生成xml*/
var xml=“”;
返回xml;
}
}

使用Azure上的流日志,我可以看到任务正在运行,但从未通过dbContext异步方法。它会挂起有什么原因吗?

如果您的代码在异步代码上阻塞,它将被挂起。我在我的博客上详细描述了这一点,但总的要点是:

  • wait
    生成调用线程时,默认情况下它首先捕获一个“上下文”。这通常是UI上下文(对于UI应用程序)、ASP.NET请求上下文(对于服务器应用程序)或线程池上下文
  • 当等待操作完成时,
    async
    状态机通过将自身调度到该上下文来恢复执行。因此,UI线程上的
    async
    方法将在该UI线程上恢复,处理ASP.NET请求的
    async
    方法将恢复处理相同的ASP.NET请求
  • 某些上下文(例如UI上下文和ASP.NET请求上下文)一次只允许一个线程进入。因此,如果在该上下文中有一个线程被阻塞,那么
    async
    方法将在恢复之前等待该线程。在这种情况下,线程在等待
    async
    方法完成时被阻塞,但由于它正在等待被阻塞的线程,因此无法执行此操作。经典的死锁

你也会发现我的帖子很有帮助。最后,我列出了“旧的阻塞方式”(应该避免)以及“新的异步方式”。本例中的相关示例是将
Task.WaitAll
替换为
wait Task。当出现所有的

连接问题时。。。您可以调试它吗?如果我将
FirstOrDefaultAsync
更改为
FirstOrDefault
并删除
wait
,它工作正常。避免死锁的强制参考:
任务。WaitAll
是一个阻塞调用。您正在积极阻止呼叫。事实上,
GenerateXml
没有
await
s,这意味着它将同步执行,编译器将给您一个关于it@PanagiotisKanavos这是正确的。您正在使用
Task.WaitAll
创建死锁。UI线程正在等待
GenerateXmlAsync
完成
GenerateXmlAsync
正在等待UI线程返回消息泵,以便它可以继续工作。也就是说,使用
WaitAll
阻止了等待I/O操作时打开的线程,该线程必须在另一个线程上启动。使用
wait Task.whalll
修复了该问题。谢谢