代码之家  ›  专栏  ›  技术社区  ›  ev vk

query.wait未完成

  •  2
  • ev vk  · 技术社区  · 8 年前

    我是MVC中使用异步方法的新手,所以我尝试了 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 回复  |  直到 8 年前
        1
  •  5
  •   TheGeneral    8 年前

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

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

    这就是为什么

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

    • 寄存器CardTokenAsync 通过调用 _dbContext.SaveChangesAsync() (仍在上下文范围内)。

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

    • 寄存器CardTokenAsync 等待 任务 返回者 保存更改同步 . 上下文被捕获并将用于继续运行 保存更改同步 方法稍后。 保存更改同步 返回未完成的 任务 ,表示 保存更改同步 方法不完整。

    • 顶层方法在 任务 返回者 保存更改同步 . 这会阻塞上下文线程。

    …

    • 最终, 保存更改同步 将完成。这就完成了 任务 是由 保存更改同步 .

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

    这将导致 死锁 . 顶级方法正在阻止上下文线程等待 寄存器CardTokenAsync 完成,和 寄存器CardTokenAsync 正在等待上下文被释放以便它可以完成。

        2
  •  4
  •   Fabio    8 年前

    从理论上讲,您应该使所有函数异步

    [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。但是阻止异步方法仍然是错误的。