C# 从数据集c执行相同代码块传递参数的线程#
让我先说明一下我是一个临时开发人员,所以我不知道我在做什么 这是在c#和.NET3.5中开发的 我当前应用程序的核心工作是连接到远程服务器,执行WMI调用,检索一些数据,然后将这些数据放入数据库。这是一个简单的healthcheck应用程序 基本代码运行良好,但我遇到了一个问题,即如果一些服务器脱机,则超时需要1分钟(这是现实的,因为网络带宽等)。我让应用程序运行了45分钟(因为40台服务器处于脱机状态),这是没有效率的,因为代码执行了45分钟和40分钟的等待时间 经过一些研究,我认为使用线程将是最好的解决方法,如果我在处理每个服务器时为其生成一个线程 这是我的线程代码:C# 从数据集c执行相同代码块传递参数的线程#,c#,.net,C#,.net,让我先说明一下我是一个临时开发人员,所以我不知道我在做什么 这是在c#和.NET3.5中开发的 我当前应用程序的核心工作是连接到远程服务器,执行WMI调用,检索一些数据,然后将这些数据放入数据库。这是一个简单的healthcheck应用程序 基本代码运行良好,但我遇到了一个问题,即如果一些服务器脱机,则超时需要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();
}
并执行一些步骤,根据返回的wmi结果将数据插入数据库。正如前面提到的,这个过程工作得很好,但问题是上面for循环中的一些线程最终使用相同的数据,并且它在每个服务器上执行多次。流程完成后,单个服务器通常最多有5条记录
根据我所做的研究,我相信这可能是一个问题,多个线程从数据集中读取相同的x值
现在我要问的问题是:
假设数据集中有10条记录:
为什么会有超过10次的死刑执行?
如果锁定数据集值,是否仍能获得性能?
有人能告诉我如何处理由多个线程传递给静态函数的变量数据的正确方向吗?Davide所指的是,在执行线程时,从
行[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();
}
for(int x=0;xexecuteSomeSteps(ip、id、connString、filepath));
ts0.Start();
}
您甚至可能会遇到一个System.ArgumentOutOfRangeException
,因为当for
循环完成时,最后一个x++
可能已经执行,使得x
比行索引高1。任何到达其行[x]
部分的线程都将抛出异常
编辑
这个问题一直困扰着我。我认为你在评论中所描述的(看起来像是一次迭代生成了额外的记录)正是修改后的闭包所做的。有几个线程恰好大致同时启动,此时所有线程的值均为
x
。您一定还发现服务器在一个时间段内被跳过,我无法想象这不会发生。尝试在线程操作中放置一个debug.writeline或console.write。当您继续循环到下一个x时,您会发现x行并不总是您所期望的。这段代码100%工作,现在剩下的就是在执行时阻塞我的主线程,因为这是在同一个计时器回扣中执行多次。这就是第一次让我困惑的地方,一次迭代似乎产生了额外的记录,但是正在执行多次迭代,因为计时器仍然有效,因为主例程继续执行。您可以使用回调函数,并且仅当所有以前的线程都回调时,才允许下一圈启动新任务。除此之外,如果您的代码能够正常工作,那么您是幸运的,因为即使线程只休眠100毫秒左右,闭包错误也很容易重现。
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();
}