我有一个ping清扫程序,可以在已定义的ip范围内的任何有效设备上恢复基本的snmp信息,并将这些结果附加到stringbuilder csv,但我似乎得到了一些重复项,如前三个:
Date IP Site MAC Manufacturer Model Serial
25/02/2016 10.65.10.8 CS 00:00:AA:C2:24:AC Dell Dell 7130cdn XDH100611
25/02/2016 10.65.10.4 CS 00:00:AA:C2:24:AC Dell Dell 7130cdn XDH100611
25/02/2016 10.65.10.3 CS 00:00:AA:C2:24:AC Dell Dell 7130cdn XDH100611
25/02/2016 10.65.10.9 CS 00:00:AA:C2:3A:57 Dell Dell 7130cdn XDH100746
25/02/2016 10.65.10.11 CS 00:15:99:48:64:33 Dell Dell 5330dn Mono Laser Printer 1ZG2FG1
25/02/2016 10.65.10.12 CS 00:15:99:45:93:70 Dell Dell 5330dn Mono Laser Printer 2HC2FG1
似乎在多线程运行时有时变量会在一个线程中更新,最终我会将重复写入csv。是否有更好的方法将变量包含在自己的线程中?我可以在全球范围内定义变量吗?下面是示例代码:
static void Main(string[] args)
{
var header = string.Format("{0},{1},{2},{3},{4},{5},{6}{7}", "Date", "IP", "Site", "MAC", "Manufacturer","Model", "Serial", Environment.NewLine);
csv.Append(header);
string[] sites = { "65" };
foreach (string site in sites)
{
string ipBase = "10." + site + ".10.";
for (int i = 1; i < 255; i++)
{
string ip = ipBase + i.ToString();
Ping p = new Ping();
p.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
countdown.AddCount();
p.SendAsync(ip, 100, ip);
Thread.Sleep(10);
}
}
File.WriteAllText("Printers.csv", csv.ToString());
File.WriteAllText("Exceptions.csv", exception.ToString());
Console.ReadLine();
}
static void p_PingCompleted(object sender, PingCompletedEventArgs e)
{
string ip = (string)e.UserState;
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
string host = ip;
string community = "public";
SimpleSnmp snmp = new SimpleSnmp(host, community);
if (!snmp.Valid)
{
exception.Append(string.Format("{0},{1},{2}{3}", DateTime.Now.ToString("dd-MM-yy"), ip, "SNMP agent host name/ip address is invalid.", Environment.NewLine));
}
Dictionary<Oid, AsnType> result = snmp.Get(SnmpVersion.Ver1,
new string[] { ".1.3.6.1.2.1.1.1.0" });
if (result == null)
{
exception.Append(string.Format("{0},{1},{2}{3}", DateTime.Now.ToString("dd-MM-yy"), ip, "no snmp result", Environment.NewLine));
}
else
{
TRYONE(ip);
}
lock (lockObj)
{
upCount++;
}
}
}
public static string WhatSite(string site)
{
string[] sitecode = site.Split('.');
if (sitecode[1] == "65")
{
site = "CS";
return site;
}
else
{
return "xx";
}
}
static void TRYONE (string ip)
{
string host = ip;
string community = "public";
model = "";
serial = "";
macaddress = "";
SimpleSnmp snmp = new SimpleSnmp(host, community);
if (!snmp.Valid)
{
exception.Append(string.Format("{0},{1},{2}{3}", DateTime.Now.ToString("dd-MM-yy"), ip, "SNMP agent host name/ip address is invalid.", Environment.NewLine));
return;
}
Dictionary<Oid, AsnType> result = snmp.Get(SnmpVersion.Ver1,
new string[] { ".1.3.6.1.2.1.25.3.2.1.3.1", ".1.3.6.1.2.1.43.5.1.1.17.1", ".1.3.6.1.4.1.11.2.4.3.1.23.0" });
if (result == null)
{
exception.Append(string.Format("{0},{1},{2}{3}", DateTime.Now.ToString("dd-MM-yy"), ip, "No results received?", Environment.NewLine));
return;
}
else
{
foreach (KeyValuePair<Oid, AsnType> kvp in result)
{
if (kvp.Key.ToString() == "1.3.6.1.2.1.25.3.2.1.3.1")
{
model = kvp.Value.ToString();
if (model.Contains(";"))
{
string[] temp = model.Split(';');
model = temp[0];
}
}
if (kvp.Key.ToString() == "1.3.6.1.2.1.43.5.1.1.17.1")
{
serial = kvp.Value.ToString();
}
if (kvp.Key.ToString() == "1.3.6.1.4.1.11.2.4.3.1.23.0")
{
macaddress = kvp.Value.ToString();
macaddress = macaddress.Replace(" ", ":");
}
}
string[] manufacturer = model.Split(' ');
Console.WriteLine("{0} {1} {2} {3} {4} {5}", ip, manufacturer[0], model, serial, macaddress, WhatSite(ip));
csv.Append(string.Format("{0},{1},{2},{3},{4},{5},{6}{7}", DateTime.Now.ToString("dd-MM-yy"), ip, WhatSite(ip), macaddress, manufacturer[0], model, serial, Environment.NewLine));
}
}
由于
答案 0 :(得分:2)
有没有更好的方法将变量包含到自己的线程中?我可以非全局定义变量吗?
您可以在全局上下文中定义变量,但可以使用ThreadLocal<T>
将其用途限制在自己的线程中。
但是,在您的情况下,您似乎想要组合多个线程的输出。实现此结果的一种方法是设置一对全局ConcurrentQueue<string>
对象,一个用于csv
,一个用于exception
,并且各个线程写入这些队列。然后主线程将等待工作线程完成,逐个读取两个队列中的字符串,并将结果写入文件。