I have 2 winforms:
- Form1
- Form2
Form1 is the main form. Form1 opens Form2. In the Form2 Load
event handler, a new background worker thread is started. When worker thread finishes, it will notify the UI thread to update Form2.
The question is, user can close Form2 while the worker thread is still running. So the Form2 may be gone by the time worker thread finishes. Then some Null Reference Exception happens when worker thread attempts to update Form2 UI.
I was planning to use a flag to indicate the Form2 existence. Every time updating the UI, the flag is checked to ensure Form2 exists. But this check-and-act pattern cannot handle the race coditions. Because the form may be closed after the check is pass but before the UI update actions are taken.
So is there some way to solve this issue?
Some code of the Form2:
private void StartComputeGraphWorker()
{// this runs on the UI thread.
try
{
this.generationFinished = false;
DisableAllControls(); //prevent user input while some background work is underway.
StartShowProgressMarquee();
ThreadStart d = new ThreadStart(WorkerStartWrapper);
worker = new Thread(d);
worker.IsBackground = true;
worker.Start();
}
catch (Exception ex)
{
Logger.LogMessage(Logger.LogLevel.Error, ex.Message);
EnableAllControls();
StopShowProgressMarquee();
}
}
private void NotifyUI(Boolean suceess)
{
if (suceess)
{
// this is on the secondary illustration form. it may NOT exist by now.
if (!this.formClosed)
{//race conditions here
this.Invoke(new MethodInvoker(ShowGraphDataInUIThread));
}
else//the form has been closed, we have no place to show the graph, just return.
{
return;
}
}
else
{
// this logs to the main input form, it always exists.
Logger.LogMessage(Logger.LogLevel.Warning, "Graph generation failed.");
}
}
private void WorkerStartWrapper()
{
try
{
RenderGraphWorker();
NotifyUI(true);
}
catch (Exception ex) // ThreadAbortException or Other Exceptions
{
Logger.LogMessage(Logger.LogLevel.Warning, ex.Message);
NotifyUI(false);
}
}
ADD 1
I checked below thread:
How to update the GUI from another thread in C#?
It's not exactly the same. My form can be gone. It's not just about cross-thread control updating.
With the BackgroundWorker approach, unsubscribing the RunWorkerCompleted event in the Form2 Closing event can solve my problem.
But I am still wondering if it is possible with Thread class.