query.wait尚未完成

时间:2018-10-21 22:59:59

标签: c# entity-framework async-await

我是MVC C#中异步方法的新手,所以我尝试了This tutorial中的一些示例

因此,我使用保存creditcardtoken

的方法对类进行了编码
public  async Task<CreditCardToken> RegisterCardTokenAsync(CreditCardToken creditCardToken)
{
    if (creditCardToken == null) return null;
    creditCardToken.number = creditCardToken.maskedNumber;
    _dbContext.CreditCardToken.Add(creditCardToken);
    var saveChanges = await (_dbContext.SaveChangesAsync());
    if (saveChanges > 0) return creditCardToken;
    else return null;
}

我的控制器有一种方法可以调用我的registerCardTokenAsync

[HttpPost]
public ActionResult IngresarTargeta(CreditCardViewModel creditCardViewModel)
{
    //do something here....
    //do another thing....

    var query = MyClass.RegisterCardTokenAsync(creditCardToken);
    query.Wait();
 }

理论上,我们使用query.Wait()来“等待”直到操作完成。我的问题是CreditCardToken已保存在数据库中,但是我的应用程序只是冻结了。

为什么会这样,我该如何解决?

据我所知,执行FirstOrDefaultAsync()时需要等待。

2 个答案:

答案 0 :(得分:5)

除非您完全了解上下文,否则不要同步等待async调用,让async传播。

public async Task<ActionResult> IngresarTargeta(CreditCardViewModel creditCardViewModel)
{
   var result = await MyClass.RegisterCardTokenAsync(creditCardToken)

这就是为什么

  • 顶级方法调用RegisterCardTokenAsync(在ASP.NET上下文中)。

  • RegisterCardTokenAsync通过调用_dbContext.SaveChangesAsync()(仍在上下文中)开始保存更改。

  • SaveChangesAsync返回未完成的Task,表示保存未完成。

  • RegisterCardTokenAsync等待Task返回的SaveChangesAsync。上下文被捕获,以后将用于继续运行SaveChangesAsync方法。 SaveChangesAsync返回未完成的Task,表示SaveChangesAsync方法不完整。

  • 顶级方法在Task返回的SaveChangesAsync上同步阻止。这会阻塞上下文线程。

...

  • 最终,SaveChangesAsync将完成。这样就完成了Task返回的SaveChangesAsync

  • RegisterCardTokenAsync的延续现在可以运行了,它等待上下文可用(以便可以在上下文中执行)。

这将导致死锁。顶级方法正在阻止上下文线程等待RegisterCardTokenAsync完成,而RegisterCardTokenAsync正在等待上下文释放以便完成。

答案 1 :(得分:4)

理论上,您应该使所有功能异步

[HttpPost]
public async Task<ActionResult> IngresarTargeta(CreditCardViewModel creditCardViewModel)
{
    //do something here....
    //do another thing....

     var token = await MyClass.RegisterCardTokenAsync(creditCardToken);
     Ok(token);
 }

非常好的资源:Don't Block on Async Code

请注意,在ASP.NET Core中,您的代码可以使用,因为它不使用SynchronizationContext。但是阻止异步方法仍然是错误的。