C# 为什么在一种情况下GetAwaiter()会阻止我的应用程序,而在另一种情况下不会阻止?
我有两个项目,都使用NET5、实体框架NET5和异步。唯一的区别是被阻止的项目使用Sql Server,而另一个使用Sqlite。但我想数据库不是原因 项目1,该项目已被阻止:C# 为什么在一种情况下GetAwaiter()会阻止我的应用程序,而在另一种情况下不会阻止?,c#,async-await,C#,Async Await,我有两个项目,都使用NET5、实体框架NET5和异步。唯一的区别是被阻止的项目使用Sql Server,而另一个使用Sqlite。但我想数据库不是原因 项目1,该项目已被阻止: public void Main() { SqlServerEFNet5 miRepository = new SqlServerEFNet5(); miRepository.GetAllMyRowsAsync().GetAwaiter().GetResult(); } public Task<
public void Main()
{
SqlServerEFNet5 miRepository = new SqlServerEFNet5();
miRepository.GetAllMyRowsAsync().GetAwaiter().GetResult();
}
public Task<List<MyType> GetAllMyRowsAsync()
{
using (ContextEfNet5 dbContext = new ContextEfNet5(_optionsDbContext))
{
return await dbContext.MyEntities.FromSqlRaw("Select * from MyType").ToListAsync().ConfigureAwait(false);
}
}
public void Main()
{
SqlServerEFNet5 miRepository=newsqlserverefnet5();
miRepository.GetAllMyRowsAsync().GetAwaiter().GetResult();
}
公共任务{返回0;});
int myIntResult=miTask.GetAwaiter().GetResult();
编辑02:另一个问题的建议解决方案对我没有帮助,因为它建议使用wait,但我不能使用它,因为我必须在构造函数中调用此异步代码,并且构造函数不能是异步的
编辑03:我在这本书中找到了一个有用的助手。好的,我明白了。死锁是由于
SynchronizationContext
造成的,正如在对您的问题的评论中多次提到的,死锁正在捕获。
通常的解决方案是使用await
,或者ConfigureAwait(false)
,您可以这样做。但是
如此处所述(第节“拦截黑客”):
如果Microsoft/EF在某种程度上使用了从旧的基于事件的异步模式的转换,那么ConfigureAwait(false)
将无效,因为上下文将被捕获
结果是他们进行了这样的转换,下面是SqlServer的SqlCommand
的源代码:
在那里查找第2996行
现在,为什么SqlLite工作正常-因为SqlLite不支持异步I/O,所以SqlLite的所有异步都是假的,您可以在SqliteCommand
的源代码中清楚地看到:
行406
这里对“假”的解释是-一个项目运行在具有
SynchronizationContext
的环境中,而另一个项目运行在具有SynchronizationContext的环境中?为什么不使用async Task Main()
并去掉GetAwaiter().GetResult()
?我将检查具有SynchronizationContext的环境。但在这两个项目中,我都没有这样做。关于为什么不使用异步任务,这是因为我在类的构造函数中使用了这段代码,在另一个作为事件处理程序的Methodo中也使用了这段代码,但不能是异步的。@GSerg在您给我的链接中告诉我,我可以使用GetAwaiter().GetResult(),而不必担心死锁,但这正是我在这两种情况下所做的。@Liam感谢您的建议,但这对我的情况没有帮助。在这两个项目中,我在主类的构造函数中使用GetAwaiter(),在第一种情况下是阻塞的,在第二种情况下不是。
private void Main()
{
MyViewModelProperty.AddRange(Service.Service.GetAllMyRowsAsync().GetAwaiter().GetResult()));
}
public static async Task<List<MyType>> GetAllMyRowsAsync()
{
using (Context myDbContext = new Context())
{
return await myDbContext.MyType.ToListAsync().ConfigureAwait(false);
}
}
Task<int> miTask = Task<int>.Run(() => { return 0; });
int myIntResult = miTask.GetAwaiter().GetResult();