2011-09-20 75 views
0

我正將其添加到備用線程中的observablecollection,並將此集合綁定到wpftoolkit的datagrid。添加到具有備用線程的可觀察集合

當這種事件發生時,oncollectionchanged通過主gui線程調用。

我看到的問題是,大部分的時間應用程序將引發:

System.ArgumentOutOfRangeException了未處理 消息=索引超出範圍。必須是非負數且小於集合的大小。 參數名稱:索引 源= mscorlib程序 PARAMNAME =指數 堆棧跟蹤: 在System.ThrowHelper.ThrowArgumentOutOfRangeException() 在System.Collections.Generic.List 1.get_Item(Int32 index) at System.Collections.ObjectModel.Collection 1.System.Collections.IList.get_Item在(的Int32索引) System.Windows.Data.ListCollectionView.InternalItemAt(的Int32索引) 在System.Windows.Controls.VirtualizingStackPanel.CleanupContainers(的Int32 firstViewport,ItemsControl的ItemsControl的) 在System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(大小限制) 微軟。 Windows.Controls.Primitives.DataGridRowsPresenter.MeasureOverride(大小約束)在C:\ dd \ WPF_1 \ src \ wpf \ src \ ControlsPack \ WPFToolkit \ DataGrid \微軟\的Windows \控制\圖元\ DataGridRowsPresenter.cs:線109 在System.Windows.FrameworkElement.MeasureCore(尺寸availableSize) 在System.Windows.UIElement.Measure(尺寸availableSize) 在System.Windows.ContextLayoutManager.UpdateLayout( ) 在System.Windows.ContextLayoutManager.UpdateLayoutCallback(對象ARG) 在System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks() 在System.Windows.Media.MediaContext.RenderMessageHandlerCore(對象resizedCompositionTarget) 在System.Windows.Media。 MediaContext.RenderMessageHandler(Object resizedCompositionTarget) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback,Object args,Boolean isSingleParameter) 在System.Windows.Threading.DispatcherOperation.InvokeImpl() 在System.Threading.ExecutionContext.runTryCode(Object的UserData) 在System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode代碼,CleanupCode backoutCode,對象的UserData) 在System.Threading.ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回調,對象狀態) 在System.Windows.Threading程序。 DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd,Int32 msg,IntPtr wParam,IntPtr lParam,Boolean &處理) 在MS.Win32.HwndWrapper.WndProc(IntPtr的HWND,MSG的Int32,IntPtr的wParam中,IntPtr的lParam的,布爾&處理) 在MS.Win32.HwndSubclass.DispatcherCallbackOperation(對象O) 在System.Windows.Threading程序。 ExceptionWrapper.InternalRealCall(代表回調,Object args,Boolean isSingleParameter) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source,Delegate callback,Object args,Boolean isSingleParameter,Delegate catchHandler) at System.Windows.Threading.Dispatcher。 InvokeImpl(DispatcherPriority優先級,TimeSpan超時,Delegate方法,Object args,Boolean isSingleParameter) 位於MS.Win32.HwndSubclass。SubclassWndProc(IntPtr的HWND,MSG的Int32,IntPtr的wParam中,IntPtr的LPARAM) 在MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG & MSG) 在System.Windows.Threading.Dispatcher.TranslateAndDispatchMessage(MSG & MSG) 在System.Windows。 Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Application.RunInternal(Window window) at Apollo.App.Main()in F:\ Workspaces \ BVS \ BVS \ Apollo \ Apollo \ obj \ Debug \ App .g.cs:line 0

有關這可能來自何處的任何想法?這裏是oncollectionchanged代碼:

protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
    { 
     using (BlockReentrancy()) 
     { 
      KeyValuePair<NotifyCollectionChangedEventHandler, CollectionChangedEventData>[] handlers = _collectionChangedHandlers.ToArray(); 

      if (handlers.Length > 0) 
      { 
       foreach (KeyValuePair<NotifyCollectionChangedEventHandler, CollectionChangedEventData> kvp in handlers) 
       { 
        if (kvp.Value.Dispatcher == null) 
        { 
         kvp.Value.Action(e); 
        } 
        else 
        { 
         kvp.Value.Dispatcher.Invoke(kvp.Value.Action, DispatcherPriority.DataBind, e); 
        } 
       } 
      } 
     } 

    } 
+0

爲什麼你自己正在處理(實現)CollectionChanged? –

+0

是否有多個線程更新集合? ListCollectionView中的CollectionChanged處理程序將在收到通知後查看列表中的項目,並且它期望狀態與通知所告知的狀態相匹配。如果另一個線程在Invoke啓動後修改集合,則會使原始通知失效。 –

+0

@HenkHolterman 這是因爲我們希望主線程上的collectionchanged事件觸發與在後臺運行的線程相關。 – Csharpfunbag

回答

0

該堆棧跟蹤的頂部暗示東西爲ListCollectionView在正常List<>走錯了。

你可能應該看看結合到SelectedItem等的代碼。

+0

雖然不是問題的絕對答案,但它是向正確方向邁出的一步。 問題是數據網格試圖測量列,因爲它看到一個集合更改了事件。 wpf線程無法控制從其他線程進入的集合更改。下次來自另一個線程的集合發生變化時,渲染過程可能中斷,無法處理來自其他線程的意外事件。 – Csharpfunbag

+0

解決的辦法是從源頭收集數據(在本例中爲sql),但使用後臺線程中的主線程添加到datagrid的項目源。從我所能理解的,這允許wpf線程成功地管理gui變更。 – Csharpfunbag

+0

@Csharpfunbag這種方法的問題在於,你失去了部分性能,強制將ItemsSource的所有添加都設爲順序。 –