让我先说明我是一名临时开发人员的问题,所以我真的不知道自己在做什么以及基础知识。
这是在c#和.net 3.5中开发的。
我当前应用程序正在做的核心是连接到远程服务器,执行WMI调用,检索一些数据,然后将这些数据放入数据库。这是一个简单的健康检查应用程序。
基本代码运行良好,但我遇到了一个问题,如果一些服务器脱机,则需要1分钟才能超时(由于网络带宽等原因,这是现实的)。我执行的应用程序运行了45分钟(因为有40台服务器处于脱机状态),效率不高,因为代码执行了45分钟和40分钟的等待时间。
经过一些研究后,我认为使用线程是最好的解决方法,如果我在处理时为每个服务器生成一个线程。
这是我的线程代码:
for (int x = 0; x < mydataSet.Tables[0].Rows.Count; x++)
{
Thread ts0 = new Thread(() =>
executeSomeSteps(mydataSet.Tables[0].Rows[x]["IPAddress"].ToString(),
mydataSet.Tables[0].Rows[x]["ID"].ToString(), connString, filepath));
ts0.Start();
}
数据集包含ID引用和IP地址。执行一些步骤函数如下所示:
static void executeSomeSteps(string IPAddress, string ID, string connstring, string filepath)
{
string executeStuff;
executeStuff = funclib.ExecuteSteps(IPAddress, ID, connstring, filepath);
executeStuff = null;
}
执行一些步骤根据返回的wmi结果将数据插入数据库。如前所述,此过程工作正常,但问题是上面for循环中的某些线程最终得到相同的数据,并且每个服务器执行多次。一旦流程完成,单个服务器通常最多有5条记录。
从我所做的研究中,我相信这可能是一个问题,多个线程从数据集中读取相同的x值。
现在问我的问题:
假设数据集中有10条记录:
为什么会发生超过10次的处决? 如果我锁定数据集值,我还能获得性能吗? 有人能指出我如何处理多个线程传递给静态函数的变量数据的正确方向吗?
答案 0 :(得分:0)
Davide所指的是,在执行线程时,Rows[x]
中捕获的值可能与创建委托时不同(甚至可能不同)。这是因为在线程开始运行时for
循环继续运行。这是一个非常普遍的问题。甚至可能在没有服务器超时的情况下发生。
这个“修改后的闭包”问题的解决方案是为每个线程使用新变量:
for (int x = 0; x < mydataSet.Tables[0].Rows.Count; x++)
{
string ip = mydataSet.Tables[0].Rows[x]["IPAddress"].ToString();
string id = mydataSet.Tables[0].Rows[x]["ID"].ToString();
Thread ts0 = new Thread(() => executeSomeSteps(ip, id, connString, filepath));
ts0.Start();
}
您甚至可能会遇到System.ArgumentOutOfRangeException
,因为当for
循环结束时,最后x++
可能已执行,使x
1高于行索引。到达其Rows[x]
部分的任何线程都会抛出异常。
修改强>
这个问题一直困扰着我。我认为你在评论中描述的内容(看起来像是通过一次迭代生成额外的记录)正是修改后的闭包所做的。一些线程碰巧大致同时开始,在那一刻都取x
的值。您还必须在一圈内发现服务器被跳过,我无法想象未发生的情况。