打开MySqlConnection时不会抛出异常吗?


14

我只是从异步和Task入手,我的代码已停止处理。当我有传入的网络数据包并且尝试与数据包处理程序中的数据库进行通信时,就会发生这种情况。

public class ClientConnectedPacket : IClientPacket
{
    private readonly EntityFactory _entityFactory;

    public ClientConnectedPacket(EntityFactory entityFactory)
    {
        _entityFactory= entityFactory;
    }

    public async Task Handle(NetworkClient client, ClientPacketReader reader)
    {
        client.Entity = await _entityFactory.CreateInstanceAsync( reader.GetValueByKey("unique_device_id"));

        // this Console.WriteLine never gets reached
        Console.WriteLine($"Client [{reader.GetValueByKey("unique_device_id")}] has connected");
    }
}

从异步任务中调用Handle方法

if (_packetRepository.TryGetPacketByName(packetName, out var packet))
{
    await packet.Handle(this, new ClientPacketReader(packetName, packetData));
}
else
{
    Console.WriteLine("Unknown packet: " + packetName);
}

这是我认为导致问题的方法

public async Task<Entity> CreateInstanceAsync(string uniqueId)
{
    await using (var dbConnection = _databaseProvider.GetConnection())
    { 
        dbConnection.SetQuery("SELECT COUNT(NULL) FROM `entities` WHERE `unique_id` = @uniqueId");
        dbConnection.AddParameter("uniqueId", uniqueId);

        var row = await dbConnection.ExecuteRowAsync();

        if (row != null)
        {
            return new Entity(uniqueId, false);
        }
    }

    return new Entity(uniqueId,true);
}

DatabaseProvider的GetConnection方法:

public DatabaseConnection GetConnection()
{
    var connection = new MySqlConnection(_connectionString);
    var command = connection.CreateCommand();

    return new DatabaseConnection(_logFactory.GetLogger(), connection, command);
}

DatabaseConnection的构造函数:

public DatabaseConnection(ILogger logger, MySqlConnection connection, MySqlCommand command)
{
    _logger = logger;

    _connection = connection;    
    _command = command;

    _connection.Open();
}

当我注释掉这一行时,它到达 Console.WriteLine

_connection.Open();

3
请注意,Oracle的MySQL Connector / NET(也称为MySql.Data)实际上并未实现任何异步操作:stackoverflow.com/a/40065501/23633如果要对MySQL使用异步操作,则应切换到nuget.org/包/ MySqlConnector
Bradley Grainger

听起来您的代码陷入了僵局。我建议在发生这种情况时闯入Visual Studio调试器,并打开“并行堆栈”窗口。如果这显示一个或多个线程具有正在某个任务(或某些同步原语)上阻塞的调用堆栈,那么您希望可以告诉您出了什么问题(或在问题中编辑更多详细信息以帮助我们)。如果在Task上没有任何线程被阻塞,则您可能有一个Task永远不会完成,也永远不会激活正在执行的代码await。这很难诊断。
布拉德利·格兰杰

您可以添加DatabaseConnection.DisposeAsync的实现吗?
eisenpony

如果您等待5分钟,最终会引发异常吗?Connection.open在尝试连接时不会返回,但在设置超时后最终将放弃。或者,您可以将连接对象上的超时值更改为一个较小的数字,该数字大于0,然后查看是否存在异常。
weichch

Answers:


1

我运行了一个POC项目,在.NET Core 3.1控制台应用程序上使用MySql.Data 8.0.19和MySqlConnector 0.63.2旋转了100个并行任务。我创建,打开连接并将其放置到每个任务的上下文中。两家供应商都可以正常运行,没有错误。

尽管库提供了异步方法签名,例如ExecuteReaderAsync()或ExecuteScalarAsync(),但MySql.Data查询却是同步运行的,而MySqlConnector确实是异步运行的。

您可能会遇到:

  • 与mysql提供程序不特别相关的死锁情况
  • 无法正确处理任务中的异常(您可以检查与任务相关的聚合异常,还可以监视mysql db日志)
  • 如果您认为MySql.Data在同步执行时运行大量并行任务,那么在您认为执行不正常时,您的执行仍然会被阻止(不返回结果)

0

MySQL的多线程必须使用独立的连接。鉴于此,多线程不是MySQL问题,而是客户端语言C#的问题。

也就是说,在不考虑MySQL的情况下构建线程,然后在每个需要执行查询的线程中创建一个连接。如果您需要在线程之间传递数据,它将由您来承担。

我通常发现优化查询消除了对应用程序进行多线程处理的诱惑。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.