axnst2
asked on
Strange WPF UI Error
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.ThrowIn validOpera tionExcept ion(Except ionResourc e resource)
at System.Collections.Generic .List`1.En umerator.M oveNextRar e()
at System.Collections.Generic .List`1.En umerator.M oveNext()
at System.Windows.Data.Collec tionView.P laceholder AwareEnume rator.Move Next()
at System.Windows.Automation. Peers.Item sControlAu tomationPe er.GetChil drenCore()
at System.Windows.Automation. Peers.List ViewAutoma tionPeer.G etChildren Core()
at System.Windows.Automation. Peers.Auto mationPeer .EnsureChi ldren()
at System.Windows.Automation. Peers.Auto mationPeer .UpdateChi ldren()
at System.Windows.Automation. Peers.Auto mationPeer .UpdateSub tree()
at System.Windows.Automation. Peers.Auto mationPeer .UpdateSub tree()
at System.Windows.ContextLayo utManager. fireAutoma tionEvents ()
at System.Windows.ContextLayo utManager. UpdateLayo ut()
at System.Windows.ContextLayo utManager. UpdateLayo utCallback (Object arg)
at System.Windows.Media.Media Context.In vokeOnRend erCallback .DoWork()
at System.Windows.Media.Media Context.Fi reInvokeOn RenderCall backs()
at System.Windows.Media.Media Context.Re nderMessag eHandlerCo re(Object resizedCompositionTarget)
at System.Windows.Media.Media Context.Re nderMessag eHandler(O bject resizedCompositionTarget)
at System.Windows.Threading.E xceptionWr apper.Inte rnalRealCa ll(Delegat e callback, Object args, Boolean isSingleParameter)
at System.Windows.Threading.E xceptionWr apper.TryC atchWhen(O bject source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.D ispatcher. WrappedInv oke(Delega te callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.D ispatcherO peration.I nvokeImpl( )
at System.Windows.Threading.D ispatcherO peration.I nvokeInSec urityConte xt(Object state)
at System.Threading.Execution Context.ru nTryCode(O bject userData)
at System.Runtime.CompilerSer vices.Runt imeHelpers .ExecuteCo deWithGuar anteedClea nup(TryCod e code, CleanupCode backoutCode, Object userData)
at System.Threading.Execution Context.Ru nInternal( ExecutionC ontext executionContext, ContextCallback callback, Object state)
at System.Threading.Execution Context.Ru n(Executio nContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.D ispatcherO peration.I nvoke()
at System.Windows.Threading.D ispatcher. ProcessQue ue()
at System.Windows.Threading.D ispatcher. WndProcHoo k(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndPr oc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.Disp atcherCall backOperat ion(Object o)
at System.Windows.Threading.E xceptionWr apper.Inte rnalRealCa ll(Delegat e callback, Object args, Boolean isSingleParameter)
at System.Windows.Threading.E xceptionWr apper.TryC atchWhen(O bject source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.D ispatcher. WrappedInv oke(Delega te callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.D ispatcher. InvokeImpl (Dispatche rPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
at System.Windows.Threading.D ispatcher. Invoke(Dis patcherPri ority priority, Delegate method, Object arg)
at MS.Win32.HwndSubclass.Subc lassWndPro c(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMetho ds.Dispatc hMessage(M SG& msg)
at System.Windows.Threading.D ispatcher. PushFrameI mpl(Dispat cherFrame frame)
at System.Windows.Threading.D ispatcher. PushFrame( Dispatcher Frame frame)
at System.Windows.Threading.D ispatcher. Run()
at System.Windows.Application .RunDispat cher(Objec t ignore)
at System.Windows.Application .RunIntern al(Window window)
at System.Windows.Application .Run(Windo w window)
at System.Windows.Application .Run()
at App.Main()
Any help would be greatly appreciated!
Thanks!
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.ThrowIn
at System.Collections.Generic
at System.Collections.Generic
at System.Windows.Data.Collec
at System.Windows.Automation.
at System.Windows.Automation.
at System.Windows.Automation.
at System.Windows.Automation.
at System.Windows.Automation.
at System.Windows.Automation.
at System.Windows.ContextLayo
at System.Windows.ContextLayo
at System.Windows.ContextLayo
at System.Windows.Media.Media
at System.Windows.Media.Media
at System.Windows.Media.Media
at System.Windows.Media.Media
at System.Windows.Threading.E
at System.Windows.Threading.E
at System.Windows.Threading.D
at System.Windows.Threading.D
at System.Windows.Threading.D
at System.Threading.Execution
at System.Runtime.CompilerSer
at System.Threading.Execution
at System.Threading.Execution
at System.Windows.Threading.D
at System.Windows.Threading.D
at System.Windows.Threading.D
at MS.Win32.HwndWrapper.WndPr
at MS.Win32.HwndSubclass.Disp
at System.Windows.Threading.E
at System.Windows.Threading.E
at System.Windows.Threading.D
at System.Windows.Threading.D
at System.Windows.Threading.D
at MS.Win32.HwndSubclass.Subc
at MS.Win32.UnsafeNativeMetho
at System.Windows.Threading.D
at System.Windows.Threading.D
at System.Windows.Threading.D
at System.Windows.Application
at System.Windows.Application
at System.Windows.Application
at System.Windows.Application
at App.Main()
Any help would be greatly appreciated!
Thanks!
ASKER
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:
m_BussLogic uses the same Lock object when changing the collection.
Anything obvious that jumps out at you?
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;
}
m_BussLogic uses the same Lock object when changing the collection.
Anything obvious that jumps out at you?
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?
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?
ASKER
"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 ConvertListToObservableCol lection function.
I really appreaciate your help LearnedOne! Please let me know where you think I am screwing things up!
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 ConvertListToObservableCol
I really appreaciate your help LearnedOne! Please let me know where you think I am screwing things up!
Let's start with a review on "lock":
lock Statement (C# Reference)
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
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.
ASKER
Unfortunately, I do not have that luxury for I am dealing with existing code... Any other suggestions?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Here is the code in the framework for MoveNextRare:
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.