2014-04-01 29 views
2

我试图创建一个方法,它在传递带有可ping主机名的数据引用时尝试ping每个主机,然后更改相应的列和行的值在ping成功。在Parallel.ForEach循环中对引用的数据表进行更改

但是我不能在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

那你为什么需要'ref'?从你的代码我看不到一个原因。而且'DataTable'线程安全? (它应该,国际海事组织,但...我们确定?) –

+0

@Adriano我很确定它*不是*; p –

回答

3

除非代码明确地说,它是线程安全的,你应该假设它不是 - 因此访问必须同步。代码中的ref没有任何用处。每个pcDataRow,这样你就可以直接访问:

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不存储数据在行(它存储在列中;不,真的)。

+0

是的,这是正确的。回复谢谢你的帮助。在这里呆了很长一段时间。初学者:D但是我有问题,如果你可能:)为什么试图从数据表中选择并行循环时,它没有找到相应的行。另一个问题是实现这个函数的最好方法是什么,所以它不锁定UI线程,并且实时显示对数据表的更改。该数据表可用作DataGridView控件的数据源。 – dazgen

+1

@dazgen'DataTable'发布变更通知;因此,这是一个**非常糟糕的主意**,在您从其他线程进行更改时让它主动连接......但是,不要冻结,总是遵循相同的规则:不要阻止UI线程 - 并且请注意,因为'Parallel.ForEach'是一个同步调用(它阻塞到所有完成),阻塞UI线程正是你正在做的。 –

相关问题