C# 在Parallel.ForEach循环中对引用的datatable进行更改
我试图创建一个方法,当传递一个带有可ping主机名的datatable引用时,该方法会尝试ping每个主机,然后根据ping成功情况更改相应列和行的值 但是,我不能在Parallel.ForEach方法中使用引用。有没有办法让这一切顺利 这是我的密码:C# 在Parallel.ForEach循环中对引用的datatable进行更改,c#,datatable,ref,parallel.foreach,C#,Datatable,Ref,Parallel.foreach,我试图创建一个方法,当传递一个带有可ping主机名的datatable引用时,该方法会尝试ping每个主机,然后根据ping成功情况更改相应列和行的值 但是,我不能在Parallel.ForEach方法中使用引用。有没有办法让这一切顺利 这是我的密码: public void checkON(ref DataTable PCS) { Parallel.ForEach(PCS.AsEnumerable(), pc => {
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";
}
}
);}
除非代码明确指出它是线程安全的,否则您应该假定它不是线程安全的,因此访问必须同步。代码中的
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
不在行中存储数据(它在列中存储数据;不,真的)。那么为什么需要ref
?从你的代码我看不出原因。此外,DataTable
线程安全吗?(我想应该是这样,但是……我们确定吗?@Adriano我很确定不是这样;是的,这是正确的。真的谢谢你的帮助。被困在这里很长时间了。初学者:D但是我有一些问题,如果你可能:)为什么尝试这样做。在并行循环中从datatable中选择它找不到相应的行。另一个问题是,实现此功能的最佳方式是什么,这样它就不会锁定UI线程,并且对datatable的更改将实时可见。此datatable用作DataGridView控件的数据源。@dazgendatatable
发布更改通知;因此,当您从其他线程进行更改时,让它主动连接是一个非常糟糕的主意。。。但为了不冻结,还是一如既往地遵循同样的规则:不要阻塞UI线程——请注意,因为Parallel.ForEach
是一个同步调用(它会阻塞直到所有调用完成),所以阻塞UI线程正是您要做的。