MySqlConnectionを開くときに例外がスローされませんか?


14

私は非同期とタスクから始めたばかりで、コードが処理を停止しました。これは、着信ネットワークパケットがあり、パケットハンドラ内のデータベースと通信しようとしたときに発生します。

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のコネクタ(MySql.Data別名)/ NETは、実際に任意の非同期操作を実装していないことに注意してください:stackoverflow.com/a/40065501/23633あなたは、MySQLとの非同期操作を使用する場合は、あなたがに切り替える必要がありますnuget.org/ packages / MySqlConnector
Bradley Grainger

コードにデッドロックがあるようです。これが発生したときにVisual Studioデバッガーに割り込んで、[並列スタック]ウィンドウを開くことをお勧めします。これにより、タスク(またはいくつかの同期プリミティブ)でブロックされているコールスタックを持つ1つ以上のスレッドが表示された場合、問題の原因を特定できる(または詳細を質問に編集して役立つ)ことができます。タスクでブロックされているスレッドが1つもない場合は、タスクが完了しておらず、タスクを実行しているコードをアクティブ化していない可能性がありますawait。それを診断するのははるかに困難です。
Bradley Grainger

DatabaseConnection.DisposeAsyncの実装を追加できますか?
eisenpony

たとえば5分間待つと、最終的に例外がスローされますか?Connection.open接続を試みている間は戻りませんが、タイムアウトが設定された後、最終的にあきらめます。または、接続オブジェクトのタイムアウト値を0より大きい小さい値に変更して、例外があるかどうかを確認することもできます。
weichch

回答:


1

.NET Core 3.1コンソールアプリケーション上のMySql.Data 8.0.19とMySqlConnector 0.63.2の両方で100の並列タスクをスピンするPOCプロジェクトを実行しました。接続を作成し、開いて、すべての単一タスクのコンテキストに配置します。どちらのプロバイダーもエラーなしで完了まで実行されます。

具体的には、MySql.Dataクエリは同期的に実行されますが、ライブラリは非同期メソッドシグネチャ(ExecuteReaderAsync()やExecuteScalarAsync()など)を提供しますが、MySqlConnectorは本当に非同期的に実行されます

あなたは以下に遭遇しているかもしれません:

  • MySQLプロバイダーに特に関係のないデッドロック状況
  • タスク内の例外を適切に処理しない(タスク関連の集計例外を検査し、mysql dbログを監視することもできます)
  • 同期的に実行されるMySql.Dataで多数の並列タスクを実行している場合、機能していないと想定しても、実行は引き続きブロックされます(結果は返されません)

0

MySQLでのマルチスレッドで、独立した接続を使用する必要があります。それを考えると、マルチスレッド化はMySQLの質問ではなく、クライアント言語のC#の問題です。

これは、MySQLのに関係なく、あなたのスレッドを構築し、あるその後、クエリを行う必要がある各スレッドで接続を作成します。スレッド間でデータを受け渡す必要がある場合は、肩にかかるでしょう。

通常、クエリを最適化すると、アプリケーションをマルチスレッド化する誘惑がなくなることがわかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.