我只是从异步和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);
}
DatabaseProvider的GetConnection方法:
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
请注意,Oracle的MySQL Connector / NET(也称为MySql.Data)实际上并未实现任何异步操作:stackoverflow.com/a/40065501/23633如果要对MySQL使用异步操作,则应切换到nuget.org/包/ MySqlConnector
—
Bradley Grainger
听起来您的代码陷入了僵局。我建议在发生这种情况时闯入Visual Studio调试器,并打开“并行堆栈”窗口。如果这显示一个或多个线程具有正在某个任务(或某些同步原语)上阻塞的调用堆栈,那么您希望可以告诉您出了什么问题(或在问题中编辑更多详细信息以帮助我们)。如果在Task上没有任何线程被阻塞,则您可能有一个Task永远不会完成,也永远不会激活正在执行的代码
—
布拉德利·格兰杰
await。这很难诊断。
您可以添加DatabaseConnection.DisposeAsync的实现吗?
—
eisenpony
如果您等待5分钟,最终会引发异常吗?
—
weichch
Connection.open在尝试连接时不会返回,但在设置超时后最终将放弃。或者,您可以将连接对象上的超时值更改为一个较小的数字,该数字大于0,然后查看是否存在异常。