需求
實現c#多線程任務定時去ping各個服務器ip,並將結果返回寫到一個集合數據
需求點
1.定時
2.多線程
3.異步
4.線程安全
代碼
using Demo;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Threading;
using Timer = System.Threading.Timer;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
static int maxThreads = 10; // 同时运行的最大异步任务数量
static List<Task> tasks = new List<Task>(); // 存储正在运行的异步任务列表
private readonly Dictionary<string, Boolean> _dict = new Dictionary<string, Boolean>();
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
// 创建用于存储任务和其对应 ID 的字典
static Dictionary<int, Task> taskDict = new Dictionary<int, Task>();
public Form1()
{
InitializeComponent();
// 设置 Timer 控件每秒触发一次 Tick 事件
//timer1.Interval = 1000;
//timer1.Enabled = true;
}
private void Form1_Load(object sender, EventArgs e)
{
// 创建计时器对象
Timer timer = new Timer(async (state) =>
{
await Task.Run(() =>
{
// 在此执行异步任务
runTask().Wait();
});
}, null, 0, 1000*60*10);
}
async Task runTask()
{
SqlHelper helper = new SqlHelper();
string sqlStr = " ";
DataTable data = helper.ExecuteQuery(sqlStr);
foreach (DataRow datarow in data.Rows)
{
int rowIndex = data.Rows.IndexOf(datarow);
Console.WriteLine("启动新任务:"+ rowIndex+" "+ datarow["ip_info"].ToString());
try
{
_rwLock.EnterWriteLock();
_dict.Add(datarow["ip_info"].ToString(), false);
// 创建新的异步任务
Task task = Task.Factory.StartNew(() => checkIp(datarow["ip_info"].ToString(), rowIndex));
// 当任务数超过最大限制时等待完成某些任务
taskDict.Add(rowIndex, task);
}catch(Exception EXP)
{
Console.WriteLine(EXP);
}
finally
{
_rwLock.ExitWriteLock();
}
// 添加到任务列表
//tasks.Add(task);
// 当任务数超过最大限制时等待完成某些任务
// 等待5秒钟
//await Task.Delay(5000);
}
Console.WriteLine("_dict 的個數為 "+_dict.Count);
}
private void checkIp(String ip,int id) {
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
// 设置ping选项
options.DontFragment = true;
//Ttl:生命周期。该值指定了ICMP数据包在网络中最多可以经过多少个路由器。
//DontFragment:禁止分段标志。如果将该值设置为true,则数据包将尝试不分片地发送。默认是false。
//Padding:填充字节。使ping数据报中的实际负载大小达到指定的值。
// 创建要发送的数据
string data2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data2);
int pingCount = 3; // 测试的次数
Boolean flag = false;
// 发送ping请求
for (int i = 0; i < pingCount&&flag==false; i++)
{
PingReply reply = pingSender.Send(ip.ToString(), 1000, buffer, options);
// 处理响应
if (reply.Status == IPStatus.Success)
{
flag = true;
Console.WriteLine("第幾個{0} 次 Reply from {1}: time={2}ms", id, reply.Address.ToString(), reply.RoundtripTime);
}
}
try
{
_rwLock.EnterWriteLock();
_dict[ip] = flag;
}
catch(Exception exp)
{
Console.WriteLine(exp);
}
finally
{
/// Console.WriteLine("任务執行完成:" + id);
// 将当前任务从任务列表中删除
taskDict.Remove(id);
_rwLock.ExitWriteLock();
}
// Application.Exit();
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
性能
ping六百個ip,耗時一分四十秒