Не виняток, що кидається під час відкриття 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);
}

Метод 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 (він же MySql.Data) насправді не реалізує жодних операцій з асинхронізацією: stackoverflow.com/a/40065501/23633 Якщо ви хочете використовувати операції асинхронізації з MySQL, вам слід перейти на nuget.org/ пакети / MySqlConnector
Bradley Grainger

Це здається, що у вас в коді тупик. Я б рекомендував проникнути в налагоджувач Visual Studio, коли це станеться, і відкрити вікно Паралельних стеків. Якщо це показує один або кілька потоків із стеками викликів, які блокуються на Завдання (або якийсь примітив синхронізації), ви, сподіваємось, зможете сказати, що відбувається не так (або відредагуйте більше деталей у питанні, щоб допомогти нам). Якщо жодна з ниток не заблокована у завданні, то, ймовірно, у вас є завдання, яке ніколи не завершується, і ніколи не активує код, який awaitна ньому працює. Це набагато складніше діагностувати.
Бредлі Грейнджер

Чи можете ви додати реалізацію 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 виконуються синхронно, хоча бібліотека забезпечує підпис методів асинхронізації, наприклад ExecuteReaderAsync () або ExecuteScalarAsync (), в той час як MySqlConnector працює справді асинхронно .

Ви можете зіткнутися з:

  • ситуація в тупиковому стані, яка не стосується конкретно постачальника mysql
  • неправильно обробляти винятки у своїх завданнях (ви можете перевірити сукупний виняток, пов’язаний із завданням, а також відстежувати журнали mysql db)
  • ви будете все ще заблоковані (не повертаючи результат), якщо ви припускаєте, що воно не працює, якщо ви виконуєте велику кількість паралельних завдань з MySql.Data під час виконання синхронно

0

Багатопотокова передача з MySQL повинна використовувати незалежні з'єднання. Зважаючи на те, що багатопотоковість - це не питання MySQL, а проблема для мови клієнта, C # у вашому запитанні.

Тобто будуйте свої потоки без огляду на MySQL, а потім створюйте з'єднання у кожному потоці, для якого потрібно робити запити. Це буде на ваших плечах, якщо вам потрібно буде передавати дані між нитками.

Зазвичай я вважаю, що оптимізація запитів усуває спокусу багатопотокових моїх додатків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.