Je commence tout juste avec async et Task et mon code a cessé de traiter. Cela se produit lorsque j'ai un paquet réseau entrant et que j'essaie de communiquer avec la base de données à l'intérieur du gestionnaire de paquets.
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");
}
}
La méthode Handle est appelée à partir d'une tâche asynchrone
if (_packetRepository.TryGetPacketByName(packetName, out var packet))
{
await packet.Handle(this, new ClientPacketReader(packetName, packetData));
}
else
{
Console.WriteLine("Unknown packet: " + packetName);
}
Voici la méthode qui, je pense, est à l'origine du problème
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éthode GetConnection de DatabaseProvider:
public DatabaseConnection GetConnection()
{
var connection = new MySqlConnection(_connectionString);
var command = connection.CreateCommand();
return new DatabaseConnection(_logFactory.GetLogger(), connection, command);
}
Constructeur de DatabaseConnection:
public DatabaseConnection(ILogger logger, MySqlConnection connection, MySqlCommand command)
{
_logger = logger;
_connection = connection;
_command = command;
_connection.Open();
}
Lorsque je commente cette ligne, elle atteint le Console.WriteLine
_connection.Open();
await
s'y trouve. C'est beaucoup plus difficile à diagnostiquer.Connection.open
ne revient pas pendant qu'il essaie de se connecter, mais abandonnera finalement après un délai d'attente défini. Ou vous pouvez changer la valeur du délai d'expiration sur l'objet de connexion en un nombre inférieur à 0 et voir s'il y a exception.Réponses:
J'ai exécuté un projet POC en faisant tourner 100 tâches parallèles avec MySql.Data 8.0.19 et MySqlConnector 0.63.2 sur l'application console .NET Core 3.1. Je crée, ouvre et supprime la connexion dans le contexte de chaque tâche. Les deux fournisseurs s'exécutent sans erreur.
Les spécificités sont que les requêtes MySql.Data s'exécutent de manière synchrone bien que la bibliothèque fournisse la signature des méthodes asynchrones, par exemple ExecuteReaderAsync () ou ExecuteScalarAsync (), tandis que MySqlConnector s'exécute de manière vraiment asynchrone .
Vous pourriez rencontrer:
la source
Le multi-threading avec MySQL doit utiliser des connexions indépendantes. Étant donné que le multithreading n'est pas une question MySQL mais un problème pour le langage client, C # dans votre question.
Autrement dit, créez vos threads sans tenir compte de MySQL, puis créez une connexion dans chaque thread qui doit effectuer des requêtes. Ce sera sur vos épaules si vous avez besoin de passer des données entre les threads.
Je trouve généralement que l'optimisation des requêtes élimine la tentation de multi-thread mes applications.
la source