C# Parallel.Foreach 未对列表中的所有项目执行操作
C# Parallel.Foreach that is not peforming action on all items in list
public static void RemoveAllNetworkPrinters()
{
ManagementScope oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
oManagementScope.Connect();
SelectQuery oSelectQuery = new SelectQuery();
oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE ServerName IS NOT NULL";
using (ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery))
{
using (ManagementObjectCollection oObjectCollection = oObjectSearcher.Get())
{
if (oObjectCollection.Count != 0)
{
foreach (ManagementObject oItem in oObjectCollection)
{
oItem.Delete();
}
}
}
}
}
public static void RemoveAllNetworkPrintersParallel()
{
ManagementScope oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
oManagementScope.Connect();
SelectQuery oSelectQuery = new SelectQuery();
oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE ServerName IS NOT NULL";
using (ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery))
{
using (ManagementObjectCollection oObjectCollection = oObjectSearcher.Get())
{
if (oObjectCollection.Count != 0)
{
Parallel.ForEach(oObjectCollection.OfType<ManagementObject>().ToList(), oItem =>
{
oItem.Delete();
});
}
}
}
}
我有一个关于 c# 中 Parallel.Foreach 的问题。我一直在测试并在我为测试目的提供的示例中看到一些奇怪的东西。当我执行此功能的非并行版本时,它工作正常,但当我执行并行版本时,1-2 个项目之间的任何地方都不会在我循环通过的列表中处理。我已经阅读了 msdn 文档,但这里一定遗漏了一些东西。我知道您不能保证订单商品会得到处理,但您认为可以保证列表中的所有商品都会得到处理吗?任何有助于理解或我做错了什么的帮助将不胜感激。谢谢
如评论中所述,ManagementObject.Delete()
不是线程安全操作,因此您不应在不同线程中使用它
MSDN
Any public static ( Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
但是如果你真的需要这样做并且你想在那里使用lock
,你可以像这样
var lockObject = new Object();
Parallel.ForEach(/*.....*/, item =>
{
lock (lockObject)
{
// do your magic here
}
});
但正如我所说 使用此代码没有意义,因为它比序号 foreach.
慢
所以,我的建议是只使用 foreach。
public static void RemoveAllNetworkPrinters()
{
ManagementScope oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
oManagementScope.Connect();
SelectQuery oSelectQuery = new SelectQuery();
oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE ServerName IS NOT NULL";
using (ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery))
{
using (ManagementObjectCollection oObjectCollection = oObjectSearcher.Get())
{
if (oObjectCollection.Count != 0)
{
foreach (ManagementObject oItem in oObjectCollection)
{
oItem.Delete();
}
}
}
}
}
public static void RemoveAllNetworkPrintersParallel()
{
ManagementScope oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
oManagementScope.Connect();
SelectQuery oSelectQuery = new SelectQuery();
oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE ServerName IS NOT NULL";
using (ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery))
{
using (ManagementObjectCollection oObjectCollection = oObjectSearcher.Get())
{
if (oObjectCollection.Count != 0)
{
Parallel.ForEach(oObjectCollection.OfType<ManagementObject>().ToList(), oItem =>
{
oItem.Delete();
});
}
}
}
}
我有一个关于 c# 中 Parallel.Foreach 的问题。我一直在测试并在我为测试目的提供的示例中看到一些奇怪的东西。当我执行此功能的非并行版本时,它工作正常,但当我执行并行版本时,1-2 个项目之间的任何地方都不会在我循环通过的列表中处理。我已经阅读了 msdn 文档,但这里一定遗漏了一些东西。我知道您不能保证订单商品会得到处理,但您认为可以保证列表中的所有商品都会得到处理吗?任何有助于理解或我做错了什么的帮助将不胜感激。谢谢
如评论中所述,ManagementObject.Delete()
不是线程安全操作,因此您不应在不同线程中使用它
MSDN
Any public static ( Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
但是如果你真的需要这样做并且你想在那里使用lock
,你可以像这样
var lockObject = new Object();
Parallel.ForEach(/*.....*/, item =>
{
lock (lockObject)
{
// do your magic here
}
});
但正如我所说 使用此代码没有意义,因为它比序号 foreach.
慢所以,我的建议是只使用 foreach。