Click here to Skip to main content
15,884,177 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
The stack trace below is the result of unhandled exception that my WPF application is throwing intermittently. I'm struggling to pinpoint where the exception is coming from. The stack trace mentions a System.Windows.Controls.DataGrid and my application only has one datagrid so I guess it's being caused by removing items from the observablecollection that is bound to the datagrid.
My AddMessage method is called a result of messages being received on multiple threads, so there's a real possibility that this is a race condition, hence my attempt at using a lock.

Is there any other way to debug this, or to get more out of the stack trace?


CoreCLR Version: 5.0.1121.47308
.NET Version: 5.0.11
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ArgumentNullException: Value cannot be null. (Parameter 'key')
   at System.Collections.Generic.Dictionary`2.Remove(TKey key)
   at System.Windows.Controls.DataGrid.OnItemsCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType)
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex(NotifyCollectionChangedEventArgs args, Int32 adjustedOldIndex, Int32 adjustedNewIndex)
   at System.Windows.Data.CollectionView.ProcessChangeLog(ArrayList changeLog, Boolean processAll)
   at System.Windows.Data.CollectionView.ProcessInvoke(Object arg)
   at MS.Internal.Data.DataBindEngine.ProcessCrossThreadRequests()
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at 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& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run()


What I have tried:

I've tried catching anything at the only place I remove items from the collection, but this doesn't help. My DataGrid is bound directly to the ObservableCollection and does not use a CollectionView.

C#
 //... in the declaration
private object _messagesCollectionLock = new object();
public ObservableCollection<MessageDiagnosticViewModel> MessageDiagnostics { get; set; } = new ObservableCollection<MessageDiagnosticViewModel>();

//... in the constructor
BindingOperations.EnableCollectionSynchronization(MessageDiagnostics, _messagesCollectionLock);

//...
              
public void AddMessage(MessageDiagnosticViewModel model)
{
   lock (_messagesCollectionLock)
   {
      if (MessageDiagnostics.Count() > _maxNoOfListItems)
      {
         try
         {
               MessageDiagnostics.RemoveAt(_maxNoOfListItems);
         }
         catch (ArgumentNullException aex)
         {
               _logger.Error(aex, "Null exception removing an item.");
         }
         catch (Exception ex)
         {
               _logger.Error(ex, "Some other exception removing an item.");
         }
      }
   }

   MessageDiagnostics.Insert(0, model);
}


XML
<DataGrid ItemsSource="{Binding MessageDiagnostics}"
                  Grid.Row="1"
                  Grid.ColumnSpan="2"
                  AutoGenerateColumns="False"
                  IsReadOnly="True"
                  CanUserSortColumns="False"
                  HeadersVisibility="Column">
Posted
Comments
[no name] 18-Jan-22 2:11am    
It's complaining about a Dictionary; not an ObservableCollection.
TheRedEye 18-Jan-22 3:39am    
Right, but I didn't know if there's an underlying use of a dictionary within the ObservableCollection, since the rest of the stack trace indicates the DataGrid.
[no name] 18-Jan-22 12:16pm    
I don't see you setting the DataContext; and for all we know, the DataGrid has no columns (AutoGenerate = false). And why isn't the Insert in the try block? We can keep guessing based on what you've been posting.
Richard Deeming 18-Jan-22 3:55am    
You're removing an item inside the lock, but adding the item outside of the lock. Try moving the Insert inside the lock.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900