C# 运行线程字符串生成器以附加csv时生成的重复项

C# 运行线程字符串生成器以附加csv时生成的重复项,c#,multithreading,C#,Multithreading,我有一个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

我有一个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));

        }
    }
static void Main(字符串[]args)
{
var header=string.Format(“{0},{1},{2},{3},{4},{5},{6}{7}”,“日期”,“IP”,“站点”,“MAC”,“制造商”,“模型”,“串行”,环境.换行符);
追加(标题);
字符串[]站点={“65”};
foreach(站点中的字符串站点)
{
字符串ipBase=“10.”+站点+“.10.”;
对于(int i=1;i<255;i++)
{
字符串ip=ipBase+i.ToString();
Ping p=新Ping();
p、 PingCompleted+=新的PingCompletedEventHandler(p_PingCompleted);
countdown.AddCount();
p、 SendAsync(ip,100,ip);
睡眠(10);
}
}            
File.writealText(“Printers.csv”,csv.ToString());
File.writealText(“Exceptions.csv”,exception.ToString());
Console.ReadLine();
}
静态无效p_PingCompleted(对象发送方,PingCompletedEventArgs e)
{
字符串ip=(字符串)e.UserState;
if(e.Reply!=null&&e.Reply.Status==IPStatus.Success)
{
字符串主机=ip;
string community=“public”;
SimpleSnmp snmp=新的SimpleSnmp(主机、社区);
如果(!snmp.Valid)
{
exception.Append(string.Format(“{0},{1},{2}{3})”,DateTime.Now.ToString(“dd-MM-yy”),ip,“SNMP代理主机名/ip地址无效。”,Environment.NewLine));
}
字典结果=snmp.Get(SnmpVersion.Ver1,
新字符串[]{.1.3.6.1.2.1.1.1.0“});
如果(结果==null)
{
exception.Append(string.Format(“{0},{1},{2}{3}”,DateTime.Now.ToString(“dd-MM-yy”),ip,“无snmp结果”,Environment.NewLine));
}
其他的
{
TRYONE(ip);
}
锁(lockObj)
{
upCount++;
}
}
}
公共静态字符串WhatSite(字符串站点)
{
字符串[]sitecode=site.Split('.');
如果(站点代码[1]=“65”)
{
site=“CS”;
返回站点;
}
其他的
{
返回“xx”;
}
}
静态无效TRYONE(字符串ip)
{
字符串主机=ip;
string community=“public”;
model=“”;
序列号=”;
macaddress=“”;
SimpleSnmp snmp=新的SimpleSnmp(主机、社区);
如果(!snmp.Valid)
{
exception.Append(string.Format(“{0},{1},{2}{3})”,DateTime.Now.ToString(“dd-MM-yy”),ip,“SNMP代理主机名/ip地址无效。”,Environment.NewLine));
返回;
}
字典结果=snmp.Get(SnmpVersion.Ver1,
新字符串[]{.1.3.6.1.2.1.25.3.2.1.3.1“,”.1.3.6.1.2.1.43.5.1.1.1.17.1“,”.1.3.6.1.4.1.11.2.4.3.1.23.0“});
如果(结果==null)
{
exception.Append(string.Format(“{0},{1},{2}{3}”,DateTime.Now.ToString(“dd-MM-yy”),ip,“未收到结果?”,Environment.NewLine));
返回;
}
其他的
{
foreach(结果中的KeyValuePair kvp)
{
如果(kvp.Key.ToString()=“1.3.6.1.2.1.25.3.2.1.3.1”)
{
model=kvp.Value.ToString();
if(model.Contains(“;”))
{
字符串[]temp=model.Split(“;”);
模型=温度[0];
}                     
}
如果(kvp.Key.ToString()=“1.3.6.1.2.1.43.5.1.1.17.1”)
{
serial=kvp.Value.ToString();
}
如果(kvp.Key.ToString()=“1.3.6.1.4.1.11.2.4.3.1.23.0”)
{
macaddress=kvp.Value.ToString();
macaddress=macaddress.Replace(“,”:”);
}
}
字符串[]制造商=model.Split(“”);
Console.WriteLine(“{0}{1}{2}{3}{4}{5}”,ip,制造商[0],型号,串行,MAC地址,WhatSite(ip));
追加(string.Format(“{0}、{1}、{2}、{3}、{4}、{5}、{6}{7}”、DateTime.Now.ToString(“dd-MM-yy”)、ip、WhatSite(ip)、macaddress、制造商[0]、型号、序列、环境.NewLine));
}
}
谢谢

有没有更好的方法将变量包含到自己的线程中?我可以非全局地定义变量吗

您可以在全局上下文中定义变量,但通过使用将它们的使用限制在自己的线程中


然而,在您的例子中,您似乎希望合并多个线程的输出。实现此结果的一种方法是设置一对全局对象,一个用于
csv
,另一个用于
exception
,并让各个线程写入这些队列。然后,主线程将等待工作线程完成,从两个队列中逐个读取字符串,并将结果写入文件。

您可能需要了解线程同步。我会使用ThreadLocal吗?在这里,TRYONE(ip)被称为,沿着这些线<代码>{Thread.AllocateNamedDataSlot(模型);Thread.AllocateNamedDataSlot(串行);Thread.AllocateNamedDataSlot(macaddress);Thread TryOn