我有一个带有Linq查询的foreach循环。
一切都运行良好,直到我将foreach更改为Parallel.ForEach:
// get the task info ---------
Log("Populate task, guf code lists ...........................");
List<SF_CO_ITEM> tasks = (from coi in ctx.SF_CO_ITEM
where coi.CO == co.ID
select coi).ToList();
// foreach (SF_CO_ITEM t in tasks)
// {
Parallel.ForEach(tasks, t =>
{
Log("Executing on t: " + t.ID);
// exception on next line:
List<SF_CO_LINE_ITEM> gufs = (from coli in ctx.SF_CO_LINE_ITEM
where coli.CO_ITEM == t.ID
select coli).ToList();
我得到的例外是:
System.AccessViolationException未处理Message = Attempted to 读或写受保护的内存。这通常表明其他 记忆已腐败。 Source = Oracle.DataAccess StackTrace: 在Oracle.DataAccess.Client.OpsCon.Open(IntPtr&amp; opsConCtx,IntPtr&amp; opsErrCtx,OpoConValCtx * pOpoConValCtx,OpoConRefCtx&amp; pOpoConRefCtx) 在Oracle.DataAccess.Client.ConnectionDispenser.Open(OpoConCtx opoConCtx) 在Oracle.DataAccess.Client.OracleConnection.Open() 在System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(布尔值 openCondition,DbConnection storeConnectionToOpen,DbConnection originalConnection,String exceptionCode,String attemptsOperation, 布尔和放大器; closeStoreConnectionOnFailure) 在System.Data.EntityClient.EntityConnection.Open() 在System.Data.Objects.ObjectContext.EnsureConnection() 在System.Data.Objects.ObjectQuery
1.GetResults(Nullable
1 forMergeOption) 在System.Data.Objects.ObjectQuery1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() at System.Collections.Generic.List
1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 source) 在ChangeOrder.Program。&lt;&gt; c_ DisplayClass19.b _16(SF_CHANGE_ORDER_ITEM t)在C:\ VS_apps \ PMConsole \ PMC中 Tools \ ChangeOrderExecution \ Program.cs:第220行 在System.Threading.Tasks.Parallel。&lt;&gt; c_ DisplayClass2d2.<ForEachWorker>b__23(Int32 i) at System.Threading.Tasks.Parallel.<>c__DisplayClassf
1.b _c() 在System.Threading.Tasks.Task.InnerInvoke() 在System.Threading.Tasks.Task.InnerInvokeWithArg(任务childTask) 在System.Threading.Tasks.Task。&lt;&gt; c_ DisplayClass7.b _6(Object ) 在System.Threading.Tasks.Task.ExecuteSelfReplicating(任务根) 在System.Threading.Tasks.Task.Execute() 在System.Threading.Tasks.Task.ExecutionContextCallback(Object obj) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean ignoreSyncCtx) 在System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task&amp; currentTaskSlot) 在System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution) 在System.Threading.Tasks.ThreadPoolTaskScheduler.TryExecuteTaskInline(任务 task,Boolean taskWasPreviouslyQueued) at System.Threading.Tasks.TaskScheduler.TryRunInline(Task task,Boolean taskWasPreviouslyQueued,Object threadStatics) 在System.Threading.Tasks.Task.InternalRunSynchronously(TaskScheduler 调度) 在System.Threading.Tasks.Task.RunSynchronously(TaskScheduler scheduler) 在System.Threading.Tasks.Parallel.ForWorker [TLocal](Int32 fromInclusive,Int32 toExclusive,ParallelOptions parallelOptions, 动作1 body, Action
2 bodyWithState,Func4 bodyWithLocal, Func
1 localInit,Action1 localFinally) at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IList
1 list,ParallelOptions parallelOptions,Action1 body, Action
2 bodyWithState,Action3 bodyWithStateAndIndex, Func
4 bodyWithStateAndLocal,Func5 bodyWithEverything, Func
1 localInit, 行动1 localFinally) at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable
1 source,ParallelOptions parallelOptions,Action1 body, Action
2 bodyWithState,Action3 bodyWithStateAndIndex, Func
4 bodyWithStateAndLocal,Func5 bodyWithEverything, Func
1 localInit, 行动1 localFinally) at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable
1来源, 行动`1机构) 在C:\ VS_apps \ PMConsole \ PMC中的ChangeOrder.Program.PerformChangeOrder(SF_CHANGE_ORDER co,SF_CLIENT_PROJECT cp,SFEntitiesQA ctx) Tools \ ChangeOrderExecution \ Program.cs:第216行 在C:\ VS_apps \ PMConsole \ PMC Tools \ ChangeOrderExecution \ Program.cs中的ChangeOrder.Program.Main(String [] args):行 1373 在System.AppDomain._nExecuteAssembly(RuntimeAssembly程序集,String [] args) 在System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String [] args) 在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 在System.Threading.ThreadHelper.ThreadStart_Context(对象状态) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean ignoreSyncCtx) 在System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,对象状态) 在System.Threading.ThreadHelper.ThreadStart()InnerException:
我不确定我需要锁定什么,因为我只是抓取信息(只是RO,对吧?)。
我考虑过添加“AsParallel”,但我的理解是PLINQ指令只会导致查询与自身并行运行。
我找不到在Parallel.ForEach循环中运行Linq查询的人的任何示例,所以我甚至不确定我正在做什么是允许的。
答案 0 :(得分:2)
为什么不单独进行连接而不是单独获取每个连接?由于它看起来像是在访问数据库,因此您的LINQ提供程序应该只编写查询并获取您正在查找的行。试试这个:
List<SF_CO_LINE_ITEM> gufs;
var query = from coi in ctx.SF_CO_ITEM
where coi.CO == co.ID
join coli in ctx.SF_CO_LINE_ITEM
on coi.ID == coli.CO_ITEM
select coli;
// Confirm what the query looks like by calling 'query.ToString()'
gufs = query.ToList();
我通常将查询与实际的枚举/实现分开,这样我就可以验证查询看起来像我想要的那样。如果这是SF_CO_ITEM
和SF_CO_LINE_ITEM
之间的1:M关系,那么您应该通过将联接更改为:
join coli in ctx.SF_CO_LINE_ITEM
on coi.ID == coli.CO_ITEM into tcoli
from tc in tcoli
select tc
至于为什么要获得此异常,可能与尝试从其他线程访问上下文有关。根据{{3}}:
Hidden Loop Body Dependencies
错误的循环依赖性分析是软件的常见来源 缺陷。请注意,所有并行循环体都不包含隐藏 依赖。这是一个容易犯的错误。
尝试共享类的实例(例如Random或。)的情况 跨并行迭代的非线程安全的DbConnection是 一个微妙依赖的例子。
因此,您唯一的选择是保持顺序而不是并行或将原始查询更改为连接,以便您第一次获得正确的数据。
希望有所帮助!