我用多线程获取指定IP段的可PING通的在线机器的IP地址,主要代码如下:
List<string> ipList = new List<string>();
private void FrmMain_Load(object sender, EventArgs e)
{
Thread[] td = new Thread[51];
Dictionary<string, int> dictionaryRangeValue = new Dictionary<string, int>();
for (int i = 0; i <= 50; i++)
{
dictionaryRangeValue.Clear();
dictionaryRangeValue.Add("rangeFrom", i * 5 + 1);
dictionaryRangeValue.Add("rangeTo", (i + 1) * 5);
td[i] = new Thread(new ParameterizedThreadStart(GetConnection));
td[i].Start(dictionaryRangeValue);
}
for (int j = 0; j <= 50; j++)
{
td[j].Join();
}
MessageBox.Show(ipList.Count.ToString());
}
private void GetConnection(object dictionaryRangeValue)
{
try
{
//获取当前在线的主机IP
Connection connection = new Connection();
string ipAddress = string.Empty;
Dictionary<string, int> rv = dictionaryRangeValue as Dictionary<string, int>;
for (int i = Convert.ToInt32(rv["rangeFrom"]); i <= Convert.ToInt32(rv["rangeTo"]); i++)
{
ipAddress = "192.168.125." + i.ToString();
if (connection.test(ipAddress))
{
ipList.Add(ipAddress);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
其中Connection 为连接类,该类只负责连接IP,应该无问题
现在的问题是在执行时,有时在出现 “给定关键字不在字典中。”的异常
有时就算不出异常,在 MessageBox.Show(ipList.Count.ToString()); 得到的结果也不对
得到的结果是2000+,里面有很多重复的值
不明白错在什么地方,请各位高手帮忙解释修改一下,谢谢
我觉得是这样一个情况,你将dictionaryRangeValue传递给线程,线程立即开始,然后再进入下一个循环,清理dictionaryRangeValu,再重新装入数据,问题就出在这里:
假如进入下一循环后清空了dictionaryRangeValue,
而这时前面的线程刚好执行到Dictionary<string, int> rv = dictionaryRangeValue as Dictionary<string, int>;
等于是拿来了一个空的Dictionary<string, int>,所以报错: “给定关键字不在字典中。”
数据重复问题也是源于这里,就是恰好在前面的线程读取Dictionary<string, int>之前将其清空,并填入了新的数据,这样前面的线程拿到的也是这次循环中的新数据,当然就会重复。
解决办法很简单,把Dictionary<string, int> dictionaryRangeValue = new Dictionary<string, int>();放进循环里去:
for (int i = 0; i <= 50; i++)
{
Dictionary<string, int> dictionaryRangeValue = new Dictionary<string, int>();
dictionaryRangeValue.Add("rangeFrom", i * 5 + 1);
dictionaryRangeValue.Add("rangeTo", (i + 1) * 5);
td[i] = new Thread(new ParameterizedThreadStart(GetConnection));
td[i].Start(dictionaryRangeValue);
}