Estoy comenzando con async y Task y mi código ha dejado de procesarse. Sucede cuando tengo un paquete de red entrante y trato de comunicarme con la base de datos dentro del controlador de paquetes.
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");
}
}
Se llama al método Handle desde una tarea asincrónica
if (_packetRepository.TryGetPacketByName(packetName, out var packet))
{
await packet.Handle(this, new ClientPacketReader(packetName, packetData));
}
else
{
Console.WriteLine("Unknown packet: " + packetName);
}
Aquí está el método que creo que está causando el problema.
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);
}
Método GetConnection de DatabaseProvider:
public DatabaseConnection GetConnection()
{
var connection = new MySqlConnection(_connectionString);
var command = connection.CreateCommand();
return new DatabaseConnection(_logFactory.GetLogger(), connection, command);
}
Constructor de DatabaseConnection:
public DatabaseConnection(ILogger logger, MySqlConnection connection, MySqlCommand command)
{
_logger = logger;
_connection = connection;
_command = command;
_connection.Open();
}
Cuando comento esta línea, llega al Console.WriteLine
_connection.Open();
await
en ella. Eso es mucho más difícil de diagnosticar.Connection.open
no regresa mientras intenta conectarse, pero finalmente se dará por vencido después de un tiempo de espera establecido. O podría cambiar el valor de tiempo de espera en el objeto de conexión a un número menor mayor que 0 y ver si hay una excepción.Respuestas:
Ejecuté un proyecto POC girando 100 tareas paralelas con MySql.Data 8.0.19 y MySqlConnector 0.63.2 en la aplicación de consola .NET Core 3.1. Creo, abro y dispongo la conexión en el contexto de cada tarea. Ambos proveedores se ejecutan hasta su finalización sin errores.
Los detalles son que las consultas MySql.Data se ejecutan sincrónicamente, aunque la biblioteca proporciona la firma de métodos asincrónicos, por ejemplo, ExecuteReaderAsync () o ExecuteScalarAsync (), mientras que MySqlConnector se ejecuta realmente de forma asincrónica .
Es posible que se encuentre con:
fuente
Los subprocesos múltiples con MySQL deben usar conexiones independientes. Dado que, el subprocesamiento múltiple no es una pregunta de MySQL sino un problema para el lenguaje del cliente, C # en su pregunta.
Es decir, construya sus hilos sin tener en cuenta MySQL, luego cree una conexión en cada hilo que necesite hacer consultas. Estará sobre sus hombros si necesita pasar datos entre los hilos.
Por lo general, encuentro que la optimización de consultas elimina la tentación de realizar múltiples subprocesos en mis aplicaciones.
fuente