Tidak terkecuali dilempar saat membuka MySqlConnection?

14

Saya baru mulai dengan async dan Task dan kode saya sudah berhenti diproses. Itu terjadi ketika saya memiliki paket jaringan masuk dan saya mencoba dan berkomunikasi dengan database di dalam pengendali paket.

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

Metode Handle dipanggil dari tugas async

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

Inilah metode yang menurut saya menyebabkan masalah

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

Metode GetConnection dari DatabaseProvider:

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

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

Konstruktor DatabaseConnection:

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

    _connection = connection;    
    _command = command;

    _connection.Open();
}

Ketika saya mengomentari baris ini, ini mencapai Console.WriteLine

_connection.Open();
AAA
sumber
3
Perlu diketahui bahwa Oracle Connector MySQL / NET (alias MySql.Data) tidak benar-benar mengimplementasikan operasi async: stackoverflow.com/a/40065501/23633 Jika Anda ingin menggunakan operasi async dengan MySQL, Anda harus beralih ke nuget.org/ paket / MySqlConnector
Bradley Grainger
Sepertinya Anda mengalami kebuntuan dalam kode Anda. Saya akan merekomendasikan membobol debugger Visual Studio ketika ini terjadi dan membuka jendela Parallel Stacks. Jika ini menunjukkan satu atau lebih utas dengan tumpukan panggilan yang memblokir pada Tugas (atau primitif sinkronisasi), maka Anda diharapkan dapat mengetahui apa yang salah (atau mengedit detail lainnya ke dalam pertanyaan untuk membantu kami). Jika tidak ada utas yang diblokir pada Tugas, maka Anda mungkin memiliki Tugas yang tidak pernah selesai, dan tidak pernah mengaktifkan kode yang ada awaitdi dalamnya. Itu jauh lebih sulit untuk didiagnosis.
Bradley Grainger
Bisakah Anda menambahkan implementasi DatabaseConnection.DisposeAsync?
eisenpony
Jika Anda menunggu selama 5 menit, apakah pada akhirnya akan memberikan pengecualian? Connection.opentidak kembali ketika sedang mencoba untuk terhubung, tetapi akhirnya akan menyerah setelah batas waktu yang ditentukan. Atau Anda dapat mengubah nilai batas waktu pada objek koneksi ke angka yang lebih kecil lebih besar dari 0, dan melihat apakah ada pengecualian.
weichch

Jawaban:

1

Saya menjalankan proyek POC yang memutar 100 tugas paralel baik dengan MySql.Data 8.0.19 dan MySqlConnector 0.63.2 pada aplikasi konsol .NET Core 3.1. Saya membuat, membuka dan membuang koneksi ke dalam konteks setiap tugas. Kedua penyedia berjalan hingga selesai tanpa kesalahan.

Secara spesifik adalah bahwa pertanyaan MySql.Data berjalan secara sinkron meskipun pustaka menyediakan tanda tangan metode async misalnya ExecuteReaderAsync () atau ExecuteScalarAsync (), sementara MySqlConnector berjalan benar-benar tidak sinkron .

Anda mungkin mengalami:

  • situasi menemui jalan buntu yang tidak secara khusus terkait dengan penyedia mysql
  • tidak menangani dengan benar pengecualian di dalam tugas Anda (Anda dapat memeriksa tugas yang terkait pengecualian agregat dan juga memantau log mysql db)
  • eksekusi Anda masih diblokir (tidak mengembalikan hasil) ketika Anda menganggap itu tidak berfungsi, jika Anda menjalankan banyak tugas paralel dengan MySql.Data saat dijalankan secara serempak
kalitsov
sumber
0

Multi-threading dengan MySQL harus menggunakan koneksi independen. Karena itu, multithreading bukan pertanyaan MySQL tetapi masalah untuk bahasa klien, C # dalam pertanyaan Anda.

Artinya, buat utas Anda tanpa memperhatikan MySQL, lalu buat koneksi di setiap utas yang perlu dilakukan kueri. Ini akan berada di pundak Anda jika Anda harus melewatkan data di antara utas.

Saya biasanya menemukan bahwa kueri pengoptimalan menghilangkan godaan untuk multi-thread aplikasi saya.

Rick James
sumber