并行.Foreach c#.net4.5.1的多线程处理
我有一个并行.Foreach c#.net4.5.1的多线程处理,c#,multithreading,linq,parallel-processing,.net-4.5,C#,Multithreading,Linq,Parallel Processing,.net 4.5,我有一个IEnumerable对象,它大约有10-15个条目,所以不是很多,但是当我尝试执行时,我遇到了一个System.IO.FileNotFoundException Parallel.Foreach(…一些linq查询…,对象=>{…stuff…}) 具有可枚举性。以下是我的代码,有时有效,有时无效: IEnumerable<UserIdentifier> userIds = script.Entries.Select(x => x.UserIdentif
IEnumerable
对象,它大约有10-15个条目,所以不是很多,但是当我尝试执行时,我遇到了一个System.IO.FileNotFoundException
Parallel.Foreach(…一些linq查询…,对象=>{…stuff…})代码>
具有可枚举性。以下是我的代码,有时有效,有时无效:
IEnumerable<UserIdentifier> userIds = script.Entries.Select(x => x.UserIdentifier).Distinct();
await Task.Factory.StartNew(() =>
{
Parallel.ForEach(userIds, async userId =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
_Log.InfoFormat("user identifier: {0}", userId);
await Task.Factory.StartNew(() =>
{
foreach (ScriptEntry se in script.Entries.Where(x => x.UserIdentifier.Equals(userId)))
{
// // Run the script //
_Log.InfoFormat("waiting {0}", se.Delay);
Task.Delay(se.Delay);
_Log.InfoFormat("running SelectionInformation{0}", se.SelectionInformation);
ExecuteSingleEntry(se);
_Log.InfoFormat("[====== SelectionInformation {1} ELAPSED TIME: {0} ======]", watch.Elapsed,
se.SelectionInformation.Verb);
}
});
watch.Stop();
_Log.InfoFormat("[====== TOTAL ELAPSED TIME: {0} ======]", watch.Elapsed);
});
});
我引用了:获取
Task.Factory.StartNew(()=>Parallel.Foreach({}))
所以我的UI不会锁定在我身上有几个原则可以应用:
。我在我的博客上描述了为什么StartNew
是危险的<代码>运行
是一种更安全、更现代的选择
async
lambda传递给Parallel.ForEach
。这没有意义,也不会正常工作Task.Delay
本身没有任何作用。您要么等待它,要么使用同步版本(Thread.Sleep
)StartNew
是没有意义的;它已经是并行的,并且在线程池线程上运行的代码正在尝试在线程池线程上启动一个新操作,并立即异步等待它??)
在应用这些原则之后:
await Task.Run(() =>
{
Parallel.ForEach(userIds, userId =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
_Log.InfoFormat("user identifier: {0}", userId);
foreach (ScriptEntry se in script.Entries.Where(x => x.UserIdentifier.Equals(userId)))
{
// // Run the script //
_Log.InfoFormat("waiting {0}", se.Delay);
Thread.Sleep(se.Delay);
_Log.InfoFormat("running SelectionInformation{0}", se.SelectionInformation);
ExecuteSingleEntry(se);
_Log.InfoFormat("[====== SelectionInformation {1} ELAPSED TIME: {0} ======]", watch.Elapsed,
se.SelectionInformation.Verb);
}
watch.Stop();
_Log.InfoFormat("[====== TOTAL ELAPSED TIME: {0} ======]", watch.Elapsed);
});
});
你为什么不试试做
ExecuteSingleEntry(se)代码>线程安全如果您在Parallel.ForEach
循环中所做的只是创建一些文件和目录,那么您也可以按顺序执行。速度可能会更高。大容量存储性能(而不是CPU)是您的瓶颈。根据ExecuteSingleEntry
的实际功能,您可以尝试将文件创建和删除逻辑放在一个文件夹中ExecuteSingleEntry
的功能远不止创建文件和目录。它进入oracle数据库并针对该数据库运行报告<创建code>.wsc
文件并将其转储到目录中,以便对返回的数据进行分析。目前我正在尝试锁定文件创建。parallel.foreach用于在一个(半)大的数据集合上一次在每台运行分析的机器上复制3-5个用户,并且execute single entry函数根据选择信息选择分析路径。
await Task.Run(() =>
{
Parallel.ForEach(userIds, userId =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
_Log.InfoFormat("user identifier: {0}", userId);
foreach (ScriptEntry se in script.Entries.Where(x => x.UserIdentifier.Equals(userId)))
{
// // Run the script //
_Log.InfoFormat("waiting {0}", se.Delay);
Thread.Sleep(se.Delay);
_Log.InfoFormat("running SelectionInformation{0}", se.SelectionInformation);
ExecuteSingleEntry(se);
_Log.InfoFormat("[====== SelectionInformation {1} ELAPSED TIME: {0} ======]", watch.Elapsed,
se.SelectionInformation.Verb);
}
watch.Stop();
_Log.InfoFormat("[====== TOTAL ELAPSED TIME: {0} ======]", watch.Elapsed);
});
});