In my application, I run a hidden dummyForm
that is created only to track the main UI thread. So, if a new form is created, then InvokeRequired
used in a fictitious form to make sure that we are in the main stream of the user interface when creating a new form.
Immediately after creating an instance of the frmStart
form frmStart
I check frmStart.InvokeRequired
and it is set to false, so there is no need to reference it here (the same for dummyForm.InvokeRequired
).
Then I got frmMyDialog
, which will use frmStart
as the parent / owner like this:
using(Create frmMyDialog on main UI thread) { frmMyDialog.Show(frmStart); }
This will throw a cross-thread exception, and it is strange that here:
frmMyDialog.InvokeRequired = false dummyForm.InvokeRequired = false frmStart.InvokeRequired = true
And is this even when I verify that dummyForm.InvokeRequired
is false when creating frmStart
?
frmMyDialog.InvokeRequired
always match dummyForm.InvokeRequired
? What's going on here?
I checked that frmStart
and dummyForm
not created at all after creating the first instance.
Edit1:
So the application begins:
public static void Main(string[] args) { _instance = new MyClientMain(parameters); Application.Run(_instance); }
The constructor of the MyClientMain class will run the installer in the static MainControl class. MainControler will be in the instanciate dummyform installation method as follows:
if (_dummyForm == null) _dummyForm = new Form();
After that, the login form will process the login, and this form will be multithreaded. When the login is complete, the MainController will be called again to initiate and open the main MDI windmo that contains frmStart. To make sure that we are in the same thread, do the following:
public static StartApplication() { if (_dummyForm.InvokeRequired) _dummyForm.Invoke(new MethodInvoker(delegate { OpenMainOrbitWindow(); }));
There is no multithreading.
Then, when the service goes to the autonomous system, an event will be triggered, and I will need to pop up frmMyDialog, but when using .ShowDialog () the dialog will be placed behind the forms, so the main or main object will be found and installed as follows:
public static Form GetActiveForm() { Form activeForm = Form.ActiveForm; if (activeForm != null) return activeForm; if (MainOrbitForm.TopMost) return MainOrbitForm; else { FormCollection openForms = Application.OpenForms; for (int i = 0; i < openForms.Count && activeForm == null; ++i) { Form openForm = openForms[i]; if (openForm.IsMdiContainer) return openForm.ActiveMdiChild; } } if (_patientForm != null) { if (_patientForm.TopMost) return _patientForm; } return null; } public static string ShowOrbitDialogReName() { frmMyDialog myDialog; Form testForm;
The problem is
myDialog.InvokeRequired = false testForm.InvokeRequired = true; MainController.DummyForm.InvokeRequired = false;
Edit2: Run and create a dummy form:
dummyForm.InvokeRequired = false Thread.CurrentThread.ManagedThreadId = 9
After successful login, we create the main form
_mainForm.InvokeRequired = false MainControl.DummyForm.InvokeRequired = false Thread.CurrentThread.ManagedThreadId = 9
Everything looks good. Then a callback (WCF) is received, and the event creates frmMyDialog in the same thread (Invoke is used in dummyForm), and then ShowDialog is used:
frmMyCustomDialog.ShowDialog(_mainForm)
This raises a CrossThreadException, and here is what it looks like at the moment:
_mainForm.InvokeRequired = true frmMyCustomDialog.InvokeRequired = false MainControl.DummyForm.InvokeRequired = false Thread.CurrentThread.ManagedThreadId = 12
Why is MainControl.DummyForm not true? ManageThreadId is not 9, but 12?