LINQ查询中的间歇性错误

时间:2014-07-02 05:54:48

标签: vb.net linq task-parallel-library entity-framework-6

我在Winforms应用程序中有以下代码,该代码是通过DataGridViewBindingSource中加载和显示数据的代码的一部分。

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

我间歇性地获得NullReferenceException,“对象引用未设置为对象的实例。”位于LoadDistributionStockRestrictionTask开头的m_oc_tDSR = New ObjectModel.ObservableCollection(Of tbl_Distribution_Stock_Restriction)(...内。这个错误可能发生在十分之一的运行中,当调试时,如果我编辑,不做任何改动,然后再次运行,错误永远不会再发生。

堆栈跟踪是:

   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()

Task.WaitAll(Tasks.ToArray, m_CTS.Token)中的行LoadDistributionStockRestrictionTask可确保加载相关实体完成,m_Context.tbl_Distribution_Stock_Restriction.Localm_CurrentSeriesm_CurrentManufacturer具有有效值。相关行上方的Debug.Print行显示发生此错误时始终如此。

任何人都可以提出解决方案。

0 个答案:

没有答案