简体   繁体   中英

No exception being thrown when opening MySqlConnection?

I'm just starting out with async and Task's and my code has stopped processing. It happens when I have an incoming network packet and I try and communicate with the database inside the packet handler.

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");
    }
}

The Handle method gets called from an async task

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

Here is the method which I think is causing the issue

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's GetConnection method:

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

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

DatabaseConnection's constructor:

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

    _connection = connection;    
    _command = command;

    _connection.Open();
}

When I comment out this line, it reaches the Console.WriteLine

_connection.Open();

I ran a POC project spinning 100 parallel tasks both with MySql.Data 8.0.19 and MySqlConnector 0.63.2 on .NET Core 3.1 console application. I create, open and dispose the connection into the context of every single task. Both providers runs to completion without errors.

The specifics are that MySql.Data queries run synchronously although the library provide async methods signature eg ExecuteReaderAsync() or ExecuteScalarAsync(), while MySqlConnector run truly asynchronously .

You may be running into:

  • a deadlock situation not specifically related to the mysql provider
  • not properly handling exceptions inside your tasks (you may inspect the task associated aggregate exception and also monitor mysql db logs)
  • you execution be still blocked (not returning result) when you assume it's not working, if you running a high number of parallel tasks with MySql.Data as it executes synchronously

Multi-threading with MySQL must use independent connections. Given that, multithreading is not a MySQL question but an issue for the client language, C# in your question.

That is, build your threads without regard to MySQL, then create a connection in each thread that needs to do queries. It will be on your shoulders if you need to pass data between the threads.

I usually find that optimizing queries eliminates the temptation to multi-thread my applications.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM