Я только начинаю с async и Task, и мой код перестал обрабатываться. Это происходит, когда у меня есть входящий сетевой пакет, и я пытаюсь связаться с базой данных внутри обработчика пакетов.
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();
await
содержащийся в ней. Это гораздо сложнее диагностировать.Connection.open
не возвращается, когда пытается подключиться, но, наконец, сдается после установленного времени ожидания. Или вы можете изменить значение времени ожидания для объекта подключения на меньшее число, большее 0, и посмотреть, есть ли исключение.Ответы:
Я запустил проект POC, включив в себя 100 параллельных задач с MySql.Data 8.0.19 и MySqlConnector 0.63.2 в консольном приложении .NET Core 3.1. Я создаю, открываю и размещаю соединение в контексте каждой отдельной задачи. Оба провайдера работает до завершения без ошибок.
Специфика заключается в том, что запросы MySql.Data выполняются синхронно, хотя библиотека предоставляет подпись асинхронных методов, например, ExecuteReaderAsync () или ExecuteScalarAsync (), тогда как MySqlConnector выполняется действительно асинхронно .
Вы можете столкнуться с:
источник
Многопоточность с MySQL должна использовать независимые соединения. Учитывая это, многопоточность - это не вопрос MySQL, а проблема клиентского языка, C # в вашем вопросе.
То есть создавайте свои потоки без учета MySQL, а затем создайте соединение в каждом потоке, который должен выполнять запросы. Это будет на ваших плечах, если вам нужно будет передавать данные между потоками.
Я обычно нахожу, что оптимизация запросов устраняет соблазн многопоточности моих приложений.
источник