ไม่มีข้อยกเว้นเมื่อถูกเปิด MySqlConnection หรือไม่


14

ฉันเพิ่งเริ่มต้นด้วย async และ Task's และรหัสของฉันหยุดการประมวลผล มันเกิดขึ้นเมื่อฉันมีแพ็คเก็ตเครือข่ายขาเข้าและฉันพยายามและสื่อสารกับฐานข้อมูลภายในตัวจัดการแพ็คเก็ต

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

วิธีการจัดการได้รับการเรียกจากงาน async

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

วิธี GetConnection ของ DatabaseProvider:

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
พึงระวังว่า MySQL Connector / NET ของ Oracle (aka MySql.Data) ไม่ได้ใช้งานการดำเนินการใด ๆ ของ async: stackoverflow.com/a/40065501/23633หากคุณต้องการใช้การทำงานแบบ async กับ MySQL คุณควรเปลี่ยนไปใช้nuget.org/ packages / MySqlConnector
Bradley Grainger

ดูเหมือนว่าคุณมีการหยุดชะงักในรหัสของคุณ ฉันขอแนะนำให้เจาะเข้าไปในดีบักเกอร์ Visual Studio เมื่อเกิดเหตุการณ์นี้ขึ้นและเปิดหน้าต่าง Parallel Stacks หากสิ่งนี้แสดงหนึ่งหรือหลายเธรดที่มีสแต็คการโทรที่กำลังบล็อกในภารกิจ (หรือดั้งเดิมบางอย่างในการซิงโครไนซ์) คุณหวังว่าจะสามารถบอกได้ว่าเกิดอะไรขึ้น (หรือแก้ไขรายละเอียดเพิ่มเติมในคำถามเพื่อช่วยเรา) หากไม่มีเธรดใดถูกบล็อกในงานแสดงว่าคุณอาจมีงานที่ไม่เสร็จสมบูรณ์และไม่เคยเปิดใช้งานรหัสที่ทำงานawaitอยู่ มันยากมากที่จะวินิจฉัย
Bradley Grainger

คุณสามารถเพิ่มการใช้งานของ DatabaseConnection.DisposeAsync ได้หรือไม่?
eisenpony

หากคุณรอประมาณ 5 นาทีในที่สุดมันจะเป็นข้อยกเว้น? Connection.openไม่ส่งคืนในขณะที่พยายามเชื่อมต่อ แต่ในที่สุดจะเลิกใช้หลังจากหมดเวลา หรือคุณสามารถเปลี่ยนค่าการหมดเวลาบนวัตถุเชื่อมต่อเป็นจำนวนที่น้อยกว่า 0 และดูว่ามีข้อยกเว้น
weichch

คำตอบ:


1

ฉันรันโครงการ POC หมุน 100 งานคู่ขนานทั้งที่มี MySql.Data 8.0.19 และ MySqlConnector 0.63.2 บนแอปพลิเคชันคอนโซล NET Core 3.1 ฉันสร้างเปิดและกำจัดการเชื่อมต่อในบริบทของทุกงาน ผู้ให้บริการทั้งสองทำงานจนเสร็จสมบูรณ์โดยไม่มีข้อผิดพลาด

เฉพาะที่คำสั่ง MySql.Data ทำงานพร้อมกันแม้ว่าห้องสมุดให้ async วิธีลายเซ็นเช่น ExecuteReaderAsync () หรือ ExecuteScalarAsync () ในขณะที่ MySqlConnector ทำงานอย่างแท้จริงถ่ายทอดสด

คุณอาจจะพบเจอ:

  • สถานการณ์การหยุดชะงักไม่เกี่ยวข้องกับผู้ให้บริการ mysql โดยเฉพาะ
  • จัดการข้อยกเว้นในงานของคุณไม่ถูกต้อง (คุณอาจตรวจสอบงานที่เกี่ยวข้องกับข้อยกเว้นรวมและตรวจสอบบันทึก mysql db)
  • การประมวลผลของคุณยังคงถูกบล็อก (ไม่ใช่ผลลัพธ์ที่ส่งคืน) เมื่อคุณคิดว่ามันไม่ทำงานหากคุณใช้งานแบบขนานจำนวนมากด้วย MySql.Data เนื่องจากมันทำงานแบบซิงโครนัส

0

การมัลติเธรดกับ MySQL จะต้องใช้การเชื่อมต่อที่เป็นอิสระ ระบุว่ามัลติเธรดไม่ได้เป็นคำถาม MySQL แต่ปัญหาสำหรับภาษาของลูกค้า C # ในคำถามของคุณ

นั่นคือสร้างเธรดของคุณโดยไม่คำนึงถึง MySQL จากนั้นสร้างการเชื่อมต่อในแต่ละเธรดที่จำเป็นต้องทำแบบสอบถาม มันจะอยู่บนไหล่ของคุณถ้าคุณต้องการส่งผ่านข้อมูลระหว่างเธรด

ฉันมักจะพบว่าการเพิ่มประสิทธิภาพการสืบค้นช่วยลดการล่อใจให้กับแอพพลิเคชั่นแบบมัลติเธรดของฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.