c# - 为什么在一种情况下 GetAwaiter() 会阻止我的应用程序而在另一个应用程序中没有被阻止?
问题描述
我有 2 个项目,都使用 Net 5、实体框架 Net 5 和异步。唯一的区别是被阻止的项目使用Sql Server,而另一个使用Sqlite。但我猜数据库不是这个原因。
项目 1,即被阻止:
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);
}
}
我的项目2,它没有被阻止:
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);
}
}
真的在我的第二个项目中我不使用原始 sql 查询,但我尝试在我的第一个项目中只使用纯 linq 并且仍然被阻止。
另外,在我的第一个项目中,我没有填充视图模型的集合,它可能会受到影响,因为它被视图使用,但在我的第二个项目中,我填充了视图模型的集合,所以它不是问题。
我不明白为什么在一种情况下它被阻止而在另一种情况下没有。
编辑01:
如果我在项目1中使用此代码,则不会被阻止:
Task<int> miTask = Task<int>.Run(() => { return 0; });
int myIntResult = miTask.GetAwaiter().GetResult();
编辑02:另一个问题的建议解决方案对我没有帮助,因为它建议使用await,但我不能使用它,因为我必须在构造函数中调用这个异步代码,而构造函数不能是异步的。
编辑 03:我在这个How would I run an async Task<T> 方法中找到了同步?它工作的帮手。
解决方案
好的,想通了。僵局是因为SynchronizationContext
它在对您的问题的评论中多次说明它正在捕获。通常解决方案是一直使用await
,或者ConfigureAwait(false)
,你正在做的。但!
如此处所述(阻止黑客部分): https ://docs.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development
如果 Microsoft/EF 在某处使用从旧的基于事件的异步模式进行转换,那么ConfigureAwait(false)
将不起作用,因为无论如何都已经捕获了上下文。
结果他们做了这样的转换,这里是SqlCommand
SqlServer 的来源:
在那里寻找第2996行。
现在为什么 SqlLite 工作正常 - 因为 SqlLite 不支持异步 I/O,所以 SqlLite 的所有异步都是假的,你可以在源代码中清楚地看到它SqliteCommand
:
https://github.com/dotnet/efcore/blob/main/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs
第406行。
“假”的解释在这里 - https://docs.microsoft.com/en-us/dotnet/standard/data/sqlite/async
推荐阅读
- html - 背景图像通过不同的元素变得不稳定
- asp.net - 在注册时为用户生成增量唯一 ID
- php - PHP 爆炸 txt 文件并对它们进行表格化
- java - 春季批处理:MySQL分页
- javascript - 如何在chart.js散点图的末尾添加一条垂直线
- ruby-on-rails - 使用多个 Rails/React 应用程序设置 DoorKeeper?
- python - 使用 BeautifulSoup 从 html 表中提取值
- reactjs - 如何将 api 中的值保存为数字 REACT js
- ubuntu-18.04 - wxPython 安装失败
- c++ - 派生传递给超级移动构造函数