Beim Öffnen von MySqlConnection wird keine Ausnahme ausgelöst?

14

Ich fange gerade mit Async und Task an und mein Code wurde nicht mehr verarbeitet. Es passiert, wenn ich ein eingehendes Netzwerkpaket habe und versuche, mit der Datenbank im Pakethandler zu kommunizieren.

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

Die Handle-Methode wird von einer asynchronen Task aufgerufen

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

Hier ist die Methode, von der ich denke, dass sie das Problem verursacht

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

GetConnection-Methode von DatabaseProvider:

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

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

Konstruktor von DatabaseConnection:

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

    _connection = connection;    
    _command = command;

    _connection.Open();
}

Wenn ich diese Zeile auskommentiere, erreicht sie die Console.WriteLine

_connection.Open();
AAA
quelle
3
Beachten Sie, dass MySQL Connector / NET von Oracle (auch bekannt als MySql.Data) keine asynchronen Vorgänge implementiert: stackoverflow.com/a/40065501/23633 Wenn Sie asynchrone Vorgänge mit MySQL verwenden möchten, sollten Sie zu nuget.org/
Bradley Grainger
Es hört sich so an, als hätten Sie einen Deadlock in Ihrem Code. Ich würde empfehlen, in diesem Fall in den Visual Studio-Debugger einzusteigen und das Fenster "Parallele Stapel" zu öffnen. Wenn dies einen oder mehrere Threads mit Aufrufstapeln anzeigt, die eine Aufgabe blockieren (oder ein Synchronisationsprimitiv), können Sie hoffentlich feststellen, was falsch läuft (oder weitere Details in der Frage bearbeiten, um uns zu helfen). Wenn keiner der Threads für eine Aufgabe blockiert ist, haben Sie wahrscheinlich eine Aufgabe, die niemals abgeschlossen wird und den darauf befindlichen Code niemals aktiviert await. Das ist viel schwieriger zu diagnostizieren.
Bradley Grainger
Können Sie die Implementierung von DatabaseConnection.DisposeAsync hinzufügen?
Eisenpony
Wenn Sie etwa 5 Minuten warten, löst dies schließlich eine Ausnahme aus? Connection.openkehrt nicht zurück, während versucht wird, eine Verbindung herzustellen, sondern gibt nach einer festgelegten Zeitüberschreitung endgültig auf. Sie können auch den Zeitlimitwert für das Verbindungsobjekt auf eine kleinere Zahl größer als 0 ändern und prüfen, ob eine Ausnahme vorliegt.
weichch

Antworten:

1

Ich habe ein POC-Projekt ausgeführt, in dem 100 parallele Aufgaben sowohl mit MySql.Data 8.0.19 als auch mit MySqlConnector 0.63.2 in der .NET Core 3.1-Konsolenanwendung ausgeführt wurden. Ich erstelle, öffne und entsorge die Verbindung im Kontext jeder einzelnen Aufgabe. Beide Anbieter laufen fehlerfrei ab.

Die Besonderheiten sind, dass MySql.Data-Abfragen synchron ausgeführt werden, obwohl die Bibliothek eine Signatur für asynchrone Methoden bereitstellt, z. B. ExecuteReaderAsync () oder ExecuteScalarAsync (), während MySqlConnector wirklich asynchron ausgeführt wird .

Möglicherweise stoßen Sie auf:

  • Eine Deadlock-Situation, die nicht speziell mit dem MySQL-Anbieter zusammenhängt
  • Ausnahmen in Ihren Aufgaben werden nicht ordnungsgemäß behandelt (Sie können die mit der Aufgabe verknüpfte aggregierte Ausnahme überprüfen und auch MySQL-Datenbankprotokolle überwachen).
  • Ihre Ausführung wird weiterhin blockiert (Ergebnis wird nicht zurückgegeben), wenn Sie davon ausgehen, dass sie nicht funktioniert, wenn Sie eine hohe Anzahl paralleler Aufgaben mit MySql.Data ausführen, während es synchron ausgeführt wird
Kalitsov
quelle
0

Multithreading mit MySQL muss unabhängige Verbindungen verwenden. Angesichts dessen ist Multithreading keine MySQL-Frage, sondern ein Problem für die Client-Sprache, C # in Ihrer Frage.

Das heißt, erstellen Sie Ihre Threads ohne Rücksicht auf MySQL und stellen Sie dann in jedem Thread eine Verbindung her, die Abfragen ausführen muss. Es liegt auf Ihren Schultern, wenn Sie Daten zwischen den Threads übertragen müssen.

Normalerweise finde ich, dass die Optimierung von Abfragen die Versuchung beseitigt, meine Anwendungen mit mehreren Threads zu versehen.

Rick James
quelle