我正在尝试创建一个方法,当使用可ping的主机名传递数据表引用时,尝试ping每个主机,然后根据ping成功更改相应列和行的值。
但是我不能在Parallel.ForEach方法中使用引用。有什么方法可以使这项工作吗?
这是我的代码:
public void checkON(ref DataTable PCS)
{
Parallel.ForEach(PCS.AsEnumerable(), pc =>
{
string loopIp = pc["Name"].ToString();
if (PingIP(loopIp))
{
DataRow[] currentpc = PCS.Select("Name = '{0}'", loopIp);
currentpc[0]["Online"] = "ON";
}
else
{
DataRow[] currentpc = PCS.Select("Name = '{0}'", loopIp);
currentpc[0]["Online"] = "OFF";
}
}
);}
答案 0 :(得分:3)
除非代码明确说明它是线程安全的,否则你应该认为它不是 - 因此必须同步访问。代码中的ref
没有用处。每个pc
都是DataRow
,因此您可以直接访问它:
string loopIp;
lock(someLockObject) {
loopIp = (string)pc["Name"];
}
string online = PingIP(loopIp) ? "ON" : "OFF";
lock(someLockObject) {
pc["Online"] = online;
}
其中someLockObject
在所有呼叫者之间共享,因为您无法对线程模型做出假设:
object someLockObject = new object();
Parallel.ForEach(PCS.AsEnumerable(), pc =>
{ ... });
特别是,您无法锁定该行,因为 DataTable
不会将数据存储在行中(它将其存储在列中;不,确实如此)。