C#多线程异步连接MySQL与SQLserver数据库
一、前言
当编写代码连接多台设备上的数据库时,如果采用同步逐个连接的方式,在网络畅通的情况下连接速度尚可,但当其中一台设备网络不佳特别是处于关机状态时,等待数据库连接同时程序无法响应的时间会大幅度增加,即使设置Connect Timeout也无法缩短等待时间,因为此时是程序在等待TCP应答,等待时间通常是由 TCP 协议本身的机制控制。
考虑到此类异常情况的处理,可以使用多线程连接技术,使用线程控制连接超时问题,而异步连接可以在进行连接的同时进行其他操作。
二、多线程异步连接数据库代码
2.1实现代码
代码使用C#编写,使用代码前需要引用三个依赖包,分别如下:
using MySql.Data.MySqlClient;
using System.Data.SqlClient;
using System.Threading;
代码支持MySQL数据库连接和SQLserver数据库连接,具体如下:
private async Task<(bool isSuccess, string message)> TryConnectWithTimeoutAsync(object conn, int timeout)
{
Stopwatch sw = new Stopwatch();
bool connectSuccess = false;
string message = "";
// 创建取消令牌源
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
// 创建连接任务
Task connectTask = Task.Run(() =>
{
try
{
sw.Start();
if(conn is SqlConnection)
{
((SqlConnection)conn).Open();
}
if (conn is MySqlConnection)
{
((MySqlConnection)conn).Open();
}
connectSuccess = true;
message = "数据库连接成功";
}
catch (Exception ex)
{
message = $"数据库连接失败:{ex.Message}";
}
}, token);
// 创建超时任务
Task timeoutTask = Task.Delay(timeout, token);
// 等待连接任务或超时任务哪个先完成
Task completedTask = await Task.WhenAny(connectTask, timeoutTask);
if (completedTask == timeoutTask)
{
// 如果超时先完成,取消连接任务
cancellationTokenSource.Cancel();
message = "数据库连接超时";
}
return (connectSuccess, message);
}
public async Task ConnectMultipleDatabasesAsync(int timeout, List<MySqlConnection> mySqlConnections)
{
var tasks = new List<Task>();
for (int i = 0; i < mySqlConnections.Count; i++)
{
tasks.Add(TryConnectWithTimeoutAsync(mySqlConnections[i], timeout));
}
var results = await Task.WhenAll(tasks); // 等待所有任务完成
for (int i = 0; i < results.Length; i++)
{
var (isSuccess, message) = results[i];
Console.WriteLine($"{message}");
}
}
2.2代码说明
上面代码定义了两个异步执行的函数,TryConnectWithTimeoutAsync和ConnectMultipleDatabasesAsync。TryConnectWithTimeoutAsync函数执行单个数据库连接任务,返回Tuple类型变量,内含一个bool类型和一个字符串类型,描述数据库连接情况。
ConnectMultipleDatabasesAsync函数执行多个数据库连接任务,接受多个数据库连接对象输入,内部调用TryConnectWithTimeoutAsync,使用timeout参数控制每个连接任务超时,单位为毫秒。
同时接受多个连接返回的连接状态,可将状态打印至控制台,也可留作它用。
2.3代码调用
实际使用时,调用的函数需要使用异步描述符async声明,示例调用代码如下:
public async void UserFunc(List<MySqlConnection> mySqlConnections)
{
await Task.Run(async () =>
{
await ConnectMultipleDatabasesAsync(mySqlConnections, 5000);//超时等待5000毫秒
});
}
参考文档
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)