Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.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# 为什么在一种情况下GetAwaiter()会阻止我的应用程序,而在另一种情况下不会阻止?_C#_Async Await - Fatal编程技术网

C# 为什么在一种情况下GetAwaiter()会阻止我的应用程序,而在另一种情况下不会阻止?

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<

我有两个项目,都使用NET5、实体框架NET5和异步。唯一的区别是被阻止的项目使用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);
    }
}
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();