I have a class setup as shown - I understand a longrunning task would be better, but this is the original state in a very trimmed down fasion. I have trimmed out anything that doesn't seem necessary to the problem.
TLDR:
- Code runs in a loop and the listed conditions (1/2/3) can be executed independently
- Logs show that
condition3
only appears to execute whencurrentParentRun.ChildRuns.Count
is > 0 - The error is thrown and caught indicating (along with other logs) that in the BeginInvoke's called function, that
currentParentRun.ChildRuns[currentParentRun.ChildRuns.Count - 1]
with a >0 count is somehow out of range.
// Class created and owned by UI
public class DataProcessor
{
private BackgroundWorker worker = new BackgroundWorker();
private ParentRun currentParentRun = null;
public DataProcessor()
{
// register background worker events
worker.WorkerSupportsCancellation = false;
worker.WorkerReportsProgress = false;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
while (process)
{
try
{
// Create a new parent
if (condition1)
{
currentParentRun = new ParentRun();
}
// Create a new child (parent will always be not null here)
if (condition2)
{
ChildRun childRun = new ChildRun();
currentParentRun.ChildRuns.Add(childRun);
}
// Call the UI and update
if (condition3)
{
ShowFinishedChildUI();
}
System.Threading.Thread.Sleep(loopDelayProcessor);
}
catch (Exception ex)
{
}
}
}
public void ShowFinishedChildUI()
{
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)(() => ShowFinishedChildUIDelegate()));
}
public void ShowFinishedChildUIDelegate()
{
// Parent is the UI being updated
parent.ShowFinishedChild(currentParentRun.ParentRunID,
currentParentRun.ChildRuns[currentParentRun.ChildRuns.Count - 1].ChildRunID);
resetParentDisplay = false;
}
}
Here, "parent" is the owning UI control and we use BeginInvoke to send call a UI function to update.
What's occuring every 20-30k new "parent" creations is occasionally, while in the middle of processing, there is an error in the ShowFinishedChildUIDelegate
function of Index was out of range. Must be non-negative and less than the size of the collection.
As far as I can verify, it is always at least non-zero, which leads me to think that somewhere between in the same line of code, the number of children changes between
currentParentRun.ChildRuns[...]
and
currentParentRun.ChildRuns.Count - 1
Is it possible that if condition2
in the main code block is fulfilled while the delegate is processing, that the same line of code can have different values, where the count of the children is greater than the number of classes in the list? That's my best guess, but I'm not sure how I can verify that.
Thanks.
More detailed error:
2021-03-19 12:00:12.8174|ERROR|GeneralLogger|UnhandledException StackTrace : at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
at System.Collections.Generic.List`1.get_Item(Int32 index)
at QASystem.Classes.DataProcessor.ShowFinishedChildUIDelegate() in D:\..\QASystem\QASystem\Classes\DataProcessor.cs:line 756
at QASystem.Classes.DataProcessor.<ShowFinishedChildUI>b__76_0() in D:\..\QASystem\QASystem\Classes\DataProcessor.cs:line 751
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 System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
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.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
at QASystem.App.Main()