【问题标题】:Is the following async enabled code liable to cause a deadlock以下启用异步的代码是否容易导致死锁
【发布时间】:2015-03-05 23:25:30
【问题描述】:
    public async Task<Foo> Execute(int id)
    {
        var parameters = new { id};

        using (var con = new SqlConnection(this.connectionString))
        {
            await con.OpenAsync();

            return await con.QueryAsync<foo>(
                "dbo.uspGetMeFoo",
                parameters,
                commandType: CommandType.StoredProcedure,
                commandTimeout: int.Parse(ConfigurationManager.AppSettings["SqlCommandTimeout"]))
                .ContinueWith(task =>  task.Result.FirstOrDefault());
        }
    }

此方法在调用类中等待,其中 - 一段时间后 - 我想在不显式阻塞的情况下使用结果。

我可以通过在调用代码中返回 Task&lt;IEnumerable&lt;Foo&gt;&gt;FirstOrDefault() 来解决这个问题,而不是使用上面的 ContinueWith

从我读过的内容来看,上面的阻塞很臭,更糟糕的是会导致问题,可能会导致死锁。我对么?

【问题讨论】:

    标签: c# asynchronous task-parallel-library async-await task


    【解决方案1】:

    在已经完成的 Task 上调用 Result(您知道如果任务继续被触发,任务将完成)不会导致死锁。

    当任务需要能够在另一个线程/上下文上安排操作才能完成时,就会导致死锁,但该线程/上下文阻塞了结果。由于任务已经完成,阻塞线程/上下文不可能阻止它完成。

    也就是说,您可以像 await 一样轻松地完成任务,而不是调用 ContinueWith

    【讨论】:

      【解决方案2】:

      正如@Servy 所说,您可以轻松编写

      public async Task<Foo> Execute(Foo foo )
      {
          var parameters = new { id = id};
      
          using (var con = new SqlConnection(this.connectionString))
          {
              var timeout = int.Parse(
                  ConfigurationManager.AppSettings["SqlCommandTimeout"]);
      
              await con.OpenAsync();
      
              var query = await con.QueryAsync<Foo>(
                  "dbo.uspGetMeFoo",
                  parameters,
                  commandType: CommandType.StoredProcedure,
                  commandTimeout: timeout);
      
              return query.FirstOrDefault();
          }
      }
      

      这不会导致死锁,除非dbo.uspGetMeFoo 做了一些意想不到的蠢事。这不会是问题中的代码的问题。

      【讨论】:

      • 我一直在寻找一种重写它的方法,这非常明智。在巩固我的想法时,我在相关且及时的地方感到困惑,可以调用 task.Result。我的第一个想法是我混合了异步和同步代码。
      • 所以实际上我只是混合了两种方法来做同样的事情。延续以这种方式更加隐含,我相信这会更符合其他地方使用的内容,并且会更符合其他地方的代码。
      • 只是因为我们在同一张赞美诗上,我可能不太清楚,我的意思是你的建议(与我提出的代码相反)似乎更有意义,并且是更好,更一致。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-15
      • 2021-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多