Vb.net LINQ查询中的间歇性错误
我在Winforms应用程序中有以下代码,它是通过Vb.net LINQ查询中的间歇性错误,vb.net,linq,task-parallel-library,entity-framework-6,Vb.net,Linq,Task Parallel Library,Entity Framework 6,我在Winforms应用程序中有以下代码,它是通过BindingSource在DataGridView中加载和显示数据的代码的一部分 Imports System.Data.Entity Imports System.Data.SqlClient Imports System.Threading Imports System.Threading.Tasks Imports ForeNET.OrderMatching Public Class frm_OrderMatching Priv
BindingSource
在DataGridView
中加载和显示数据的代码的一部分
Imports System.Data.Entity
Imports System.Data.SqlClient
Imports System.Threading
Imports System.Threading.Tasks
Imports ForeNET.OrderMatching
Public Class frm_OrderMatching
Private m_Context As ForeContext
Private m_CurrentManufacturer As Byte = 0
Private m_CurrentSeries As String = ""
Private m_mreSeriesManfSet As ManualResetEvent
Private m_oc_tDSR As ObjectModel.ObservableCollection(Of tbl_Distribution_Stock_Restriction)
Private m_tLoadQryDistributionAllOrders As Task
Private m_tLoadSeriesManufacturer As Task
Private Sub LoadDistributionStockRestrictionTask()
Dim STime As DateTime = DateTime.Now, ETime As DateTime
If Not m_CTS.Token.IsCancellationRequested Then
DoDBContextAction(DBActivityType.Downloading, TimeSpan.FromSeconds(60), True, {False}, Sub() m_Context.tbl_Distribution_Stock_Restriction.Load())
Dim Tasks As List(Of Task) = New List(Of Task)
If m_tLoadQryDistributionAllOrders IsNot Nothing Then Tasks.Add(m_tLoadQryDistributionAllOrders)
If m_tLoadSeriesManufacturer IsNot Nothing Then Tasks.Add(m_tLoadSeriesManufacturer)
Task.WaitAll(Tasks.ToArray, m_CTS.Token)
DoDBContextAction(DBActivityType.Downloading, TimeSpan.FromSeconds(60), False, {True}, Sub() bs_tbl_Distribution_Stock_Restriction.ResetBindings(False))
m_mreSeriesManfSet.WaitOne(TimeSpan.FromSeconds(60))
If m_oc_tDSR IsNot Nothing Then RemoveHandler m_oc_tDSR.CollectionChanged, AddressOf m_oc_tDSR_CollectionChanged
'Debug.Print(m_Context.tbl_Distribution_Stock_Restriction.Local.ToString)
'Debug.Print(m_CurrentSeries)
'Debug.Print(m_CurrentManufacturer)
m_oc_tDSR = New ObjectModel.ObservableCollection(Of tbl_Distribution_Stock_Restriction)(From tDSR As tbl_Distribution_Stock_Restriction In m_Context.tbl_Distribution_Stock_Restriction.Local
Where (tDSR.AUS_SRS_CD = m_CurrentSeries And tDSR.ManufacturerID = m_CurrentManufacturer)
Select tDSR)
DoDBContextAction(DBActivityType.Downloading, TimeSpan.FromSeconds(60), False, {True}, Sub()
bs_tbl_Distribution_Stock_Restriction.DataSource = m_oc_tDSR
bs_tbl_Distribution_Stock_Restriction.ResetBindings(False)
End Sub)
AddHandler m_oc_tDSR.CollectionChanged, AddressOf m_oc_tDSR_CollectionChanged
End If
End Sub
Private Function DoDBContextAction(ActivityType As DBActivityType, Timeout As TimeSpan?, DoLock As Boolean, DoInvoke() As Boolean, ParamArray Action() As Action)
Dim Saved As Boolean = False, XLoadingBlocked As Boolean = False
If DoInvoke.Length <> Action.Length Then
Throw New ArgumentException("The number of elements in the DoInvoke() and Action() arrays must be the same.", "DoInvoke, Action")
End If
Do
If Not DoLock Then
For Ctr As Integer = 0 To Action.GetUpperBound(0)
If DoInvoke(Ctr) And Me.InvokeRequired Then
Me.Invoke(Action(Ctr))
Else
Action(Ctr)()
End If
Next
Saved = True
ElseIf Monitor.TryEnter(m_oDataContextLock, TimeSpan.FromMilliseconds(100)) Then
If XLoadingBlocked Then
' ...
XLoadingBlocked = False
' ...
End If
Try
For Ctr As Integer = 0 To Action.GetUpperBound(0)
If DoInvoke(Ctr) And Me.InvokeRequired Then
Me.Invoke(Action(Ctr))
Else
Action(Ctr)()
End If
Next
Saved = True
Catch ex As Exception
Throw
Finally
Monitor.Exit(m_oDataContextLock)
End Try
Else
If Not XLoadingBlocked Then
' ...
XLoadingBlocked = True
' ...
End If
Thread.Yield()
End If
Loop Until Saved Or (Timeout.HasValue AndAlso DateTime.Now - StartTime > Timeout.Value)
' ...
Return Saved
End Function
Private Sub frm_OrderMatching_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
' Load Data...
m_Context = New ForeContext
With m_Context
.Database.Log = Sub(S As String) Debug.WriteLine(S)
.Configuration.LazyLoadingEnabled = False
Dim ConnStr As String = My.Settings.ConnectionString & ";multipleactiveresultsets=True;App=EntityFramework"
With .Database.Connection
If .ConnectionString <> ConnStr Or .State = ConnectionState.Closed Then
If .State <> ConnectionState.Closed Then
.Close()
End If
.ConnectionString = ConnStr
.Open()
End If
End With
End With
AddHandler DirectCast(m_Context, Infrastructure.IObjectContextAdapter).ObjectContext.SavingChanges, AddressOf ObjectContext_SavingChanges
m_CTS = New CancellationTokenSource
m_tsScheduler = New LimitedConcurrencyReprioritizableTaskScheduler(4)
m_lTaskList = New List(Of Task)
m_tLoadManufacturers = New Task(AddressOf LoadManufacturersTask, m_CTS.Token)
m_tLoadCrossBorder = New Task(AddressOf LoadCrossBorderTask, m_CTS.Token)
m_tLoadDistributionStockModyrsPermitted = New Task(AddressOf LoadDistributionStockModyrsPermittedTask, m_CTS.Token)
m_tLoadSeriesManufacturer = New Task(AddressOf LoadSeriesManufacturerTask, m_CTS.Token)
m_tLoadDistributionOrdersPermittedEvent = New Task(AddressOf LoadDistributionOrdersPermittedEventsTask, m_CTS.Token)
m_tLoadDistributionStockPermittedEvents = New task(AddressOf LoadDistributionStockPermittedEventsTask, m_CTS.Token)
m_tLoadLayers = New Task(AddressOf LoadLayersTask, m_CTS.Token)
m_tLoadDistributionSeriesManufacturersLayers = New Task(AddressOf LoadDistributionSeriesManufacturersLayersTask, m_CTS.Token)
m_tLoadDistributionOrdersRestriction = New Task(AddressOf LoadDistributionOrdersRestrictionTask, m_CTS.Token)
m_tLoadDistributionStockRestriction = New Task(AddressOf LoadDistributionStockRestrictionTask, m_CTS.Token)
m_tLoadFAWModel = New Task(AddressOf LoadFAWModelTask, m_CTS.Token)
m_tLoadPrimaryDealerGroup = New Task(AddressOf LoadPrimaryDealerGroupTask, m_CTS.Token)
m_tLoadModelCodes = New Task(AddressOf LoadModelCodesTask, m_CTS.Token)
m_tLoadMatchedOrdersTask = New Task(AddressOf LoadMatchedOrdersTask, m_CTS.Token)
m_tChangeDMOAFilterTask = Task.Factory.ContinueWhenAll({m_tLoadSeriesManufacturer, m_tLoadPrimaryDealerGroup}, AddressOf ChangeDMOAFilterTask, m_CTS.Token, TaskContinuationOptions.None, m_tsScheduler)
m_tChangeFMFilterTask = Task.Factory.ContinueWhenAll({m_tLoadSeriesManufacturer, m_tLoadFAWModel, m_tLoadModelCodes}, AddressOf ChangeFMFilterTask, m_CTS.Token, TaskContinuationOptions.None, m_tsScheduler)
m_lTaskList.AddRange({m_tLoadLayers, m_tLoadManufacturers, m_tLoadCrossBorder, m_tLoadSeriesManufacturer, m_tLoadDistributionOrdersPermittedEvent, m_tLoadDistributionStockPermittedEvents, m_tLoadFAWModel, m_tLoadDistributionStockModyrsPermitted, _
m_tLoadDistributionOrdersRestriction, m_tLoadDistributionStockRestriction, m_tLoadPrimaryDealerGroup, m_tLoadModelCodes, m_tLoadMatchedOrdersTask, m_tChangeFMFilterTask})
m_tLoadComplete = Task.Factory.ContinueWhenAll(m_lTaskList.ToArray, AddressOf LoadCompleteTask, m_CTS.Token, TaskContinuationOptions.None, m_tsScheduler)
m_tLoadManufacturers.Start(m_tsScheduler)
m_tLoadCrossBorder.Start(m_tsScheduler)
m_tLoadDistributionStockModyrsPermitted.Start(m_tsScheduler)
m_tLoadSeriesManufacturer.Start(m_tsScheduler)
m_tLoadDistributionOrdersPermittedEvent.Start(m_tsScheduler)
m_tLoadDistributionStockPermittedEvents.Start(m_tsScheduler)
m_tLoadLayers.Start(m_tsScheduler)
m_tLoadDistributionSeriesManufacturersLayers.Start(m_tsScheduler)
m_tLoadDistributionOrdersRestriction.Start(m_tsScheduler)
m_tLoadDistributionStockRestriction.Start(m_tsScheduler)
m_tLoadFAWModel.Start(m_tsScheduler)
m_tLoadPrimaryDealerGroup.Start(m_tsScheduler)
m_tLoadModelCodes.Start(m_tsScheduler)
m_tLoadMatchedOrdersTask.Start(m_tsScheduler)
End Sub
End Class
LoadDistributionStockRestrictionTask
中的行Task.WaitAll(Tasks.ToArray,m_CTS.Token)
确保加载依赖实体完成,并且m_Context.tbl_Distribution_Stock_Restriction.Local
、m_CurrentSeries
和m_CurrentManufacturer
具有有效值。有问题的行上方的Debug.Print行表明,发生此错误时总是这样
谁能提出一个解决方案。在哪里可以实例化
m_上下文
呢?顺便说一句,你的VB.Net很难阅读。换行符是你的朋友。根据微软的.Net编码惯例,匈牙利符号不是。@DouglasBarbin,我添加了代码来显示m_Context
被实例化的位置。很抱歉没有可读性。当你设置断点时,什么是null(“Nothing”)?@DouglasBarbin,我不知道如何准确地找出什么变量是意外的Nothing
。如果我跳过一步或进入LINQ,那么错误永远不会发生。即使出现错误,上述三条Debug.Print
语句始终会导致输出正确的值(即notNothing
)。如果我没有单步执行,那么我就无法检查内部LINQ变量。
at System.Data.Entity.Core.Objects.ObjectStateManager.PerformAdd(IList`1 entries)
at System.Data.Entity.Core.Objects.ObjectStateManager.AlignChangesInRelationships(IList`1 entries)
at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()
at System.Data.Entity.Core.Objects.ObjectContext.DetectChanges()
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)
at System.Data.Entity.Internal.Linq.InternalSet`1.get_Local()
at System.Data.Entity.DbSet`1.get_Local()
at ForeNET.frm_OrderMatching.LoadDistributionStockRestrictionTask() in C:\Users\jzg48k\Documents\Visual Studio 2010\Projects\Fore GUI\Fore .NET\Forms\frm_OrderMatching.vb:line 1450
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()