You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Mysql.Data至8.*后Dapper QueryAsync调用永久挂起问题

问题分析与解决方案

问题根源

这是同步阻塞异步代码导致的死锁,MySQL 8.x版本的MySql.Data驱动对异步操作的上下文依赖更严格,直接触发了这个隐藏问题:

  • 异步方法QueryAsync默认会捕获当前线程的同步上下文(比如ASP.NET的SynchronizationContext)
  • 调用方用.GetAwaiter().GetResult()同步阻塞时,会占用这个上下文不放
  • 异步方法执行完成后需要回到原上下文处理结果,但上下文已被阻塞,最终形成互相等待的死锁

核心解决方案:全程异步(推荐)

不要在同步方法里阻塞调用异步方法,将调用方也改为异步实现:

1. 修改调用方法为异步

private async Task<bool> IsGapLiveSyncEnabled(Guid clientId)
{
    return await _clientsService.IsLiveResultsEnabled(clientId);
}

2. 优化原异步方法(可选,更规范)

将同步的connection.Open()改为异步的OpenAsync,并全程添加ConfigureAwait(false)避免捕获不必要的上下文:

public async Task<bool> IsLiveResultsEnabled(Guid clientId)
{          
    using (var connection = new MySqlConnection(_connectionString))
    {
        await connection.OpenAsync().ConfigureAwait(false);

        var result = await connection.QueryAsync<bool>(
            @"SELECT someField FROM someTable WHERE Id = @clientId",
            new { clientId })
            .ConfigureAwait(false);

        return result.FirstOrDefault();
    }
}

临时替代方案(无法修改调用方时)

如果受限于老代码必须同步调用,可以将异步操作放到线程池线程执行,避免捕获原上下文:

private bool IsGapLiveSyncEnabled(Guid clientId)
{
    return Task.Run(() => _clientsService.IsLiveResultsEnabled(clientId)).GetAwaiter().GetResult();
}

注意:此方案仅作为临时妥协,长期来看建议逐步迁移为全程异步模式,彻底避免死锁和性能损耗。

内容的提问来源于stack exchange,提问作者kosnkov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:05:15