?
Solved

Strange WPF UI Error

Posted on 2012-03-15
7
Medium Priority
?
588 Views
Last Modified: 2012-05-09
Hi Experts,

     I am getting a strange error in a WPF application.  The app displays data in a ListView(s) that use a List<> of custom classes (that implement INotifyPropertyChanged) as its ItemsSource.  The List<> gets changed all the time (add/remove/change items in the List<>, and sometimes even reload the ItemsSource all together) The app will run fine for sometimes hours and all of the sudden it'll just crash.  I have put error handling around all of the functions that I can think of that could cause the error and I caught nothing.  Finally, I put in a thing that catches all unhandled exceptions and I finally got the error message to dump into a log file.  Below is the error:

Error message:
   Collection was modified; enumeration operation may not execute.

Occured at:
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at System.Windows.Data.CollectionView.PlaceholderAwareEnumerator.MoveNext()
   at System.Windows.Automation.Peers.ItemsControlAutomationPeer.GetChildrenCore()
   at System.Windows.Automation.Peers.ListViewAutomationPeer.GetChildrenCore()
   at System.Windows.Automation.Peers.AutomationPeer.EnsureChildren()
   at System.Windows.Automation.Peers.AutomationPeer.UpdateChildren()
   at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
   at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
   at System.Windows.ContextLayoutManager.fireAutomationEvents()
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
   at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, 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.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext 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, Boolean isSingleParameter)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   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(Window window)
   at System.Windows.Application.Run()
   at App.Main()

Any help would be greatly appreciated!

Thanks!
0
Comment
Question by:axnst2
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 37726172
That is a strange error, and it looks like an issue with code that is not thread-safe.

Here is the code in the framework for MoveNextRare:

private bool MoveNextRare()
    {
        if (this.version != this.list._version)
        {
            ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
        }
        this.index = this.list._size + 1;
        this.current = default(T);
        return false;
    }

Open in new window


It compares the version for the Enumerator<T> with the version from the List<T> instance, and if they are different, then something else has changed the value, and you have a mismatch.
0
 

Author Comment

by:axnst2
ID: 37726288
Any ideas on what could be causing it?  I have background thread that is constantly changing the List, but the UI should have it's own instance so i am not sure.  Below is my code:

void UpdateTaskList()
        {
            try
            {
                m_UITimer.Stop();

                lock (m_BussLogic.Lock)
                {
                    lvMoving_Tasks.ItemsSource = CUtility.ConvertListToObservableCollection(m_BussLogic.CurrentMovingTasks);
                    lvMoving_Tasks.UpdateLayout();
                }

                if (m_RefreshOfMasterListsRequired)
                {
                    m_RefreshOfMasterListsRequired = false;

                    lock (m_BussLogic.Lock)
                    {
                        lvPriority_Tasks.ItemsSource = CUtility.ConvertListToObservableCollection(m_BussLogic.CurrentPriorityTasks);
                        lvPriority_Tasks.UpdateLayout();
                    }

                    System.Threading.Thread.Sleep(100);

                    lock (m_BussLogic.Lock)
                    {
                        lvDiscretionary_Tasks.ItemsSource = CUtility.ConvertListToObservableCollection(m_BussLogic.CurrentDiscretionaryTasks);
                        lvDiscretionary_Tasks.UpdateLayout();
                    }
                }

                lock (m_BussLogic.Lock)
                {
                    for (int index = 0; index < m_BussLogic.CurrentFilteredTasks.Count; index++)
                    {
                        if (index < m_BussLogic.CurrentFilteredTasks.Count &&   // Just in case the collection got modified
                            m_BussLogic.CurrentFilteredTasks[index] != null)
                            m_BussLogic.CurrentFilteredTasks[index].Refresh();
                    }
                }
            }
            catch (Exception er)
            {
                HandleError(er);
            }
            finally
            {
                m_UITimer.Start();
            }
        }


public static ObservableCollection<CLocalTaskItem> ConvertListToObservableCollection(List<CLocalTaskItem> listToConvert)
        {
            ObservableCollection<CLocalTaskItem> observableTasks = new ObservableCollection<CLocalTaskItem>();

            for (int index = 0; index < listToConvert.Count; index++)
            {
                if (index < listToConvert.Count &&   // Just in case the collection got modified
                    listToConvert[index] != null)
                    observableTasks.Add(listToConvert[index]);
            } 

            return observableTasks;
        }

Open in new window


m_BussLogic uses the same Lock object when changing the collection.

Anything obvious that jumps out at you?
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 37727219
What "m_BussLogic.Lock" is in this line?  How is it declared?

lock (m_BussLogic.Lock)

"I have background thread that is constantly changing the List, but the UI should have it's own instance so i am not sure. "

How does the UI get its own instance?  Are you creating a deep copy with a different reference?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:axnst2
ID: 37729386
"What "m_BussLogic.Lock" is in this line?  How is it declared?"

               In CBussLogic:

               volatile object m_Lock = new object();

               public object Lock
               {
                     get { return m_Lock; }
                     set { m_Lock = value; }
              }

              Should I maybe make m_Lock static?

"How does the UI get its own instance?  Are you creating a deep copy with a different reference?"

              Please look at my last post and the ConvertListToObservableCollection function.


I really appreaciate your help LearnedOne!  Please let me know where you think I am screwing things up!
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 37729450
Let's start with a review on "lock":

lock Statement (C# Reference)
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

In general, avoid locking on a public type, or instances beyond your code's control.
0
 

Author Comment

by:axnst2
ID: 37729674
Unfortunately, I do not have that luxury for I am dealing with existing code...  Any other suggestions?
0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 2000 total points
ID: 37730001
Are you working with one-way, or two-way binding with what looks like a ListView (lvPriority_Tasks)?
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
Suggested Courses

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question