Reputation: 2866
Because this is turning out to be quite a large project and I often need to access objects in other forms from a class I firstly create a static variable in my program.cs class of type 'MainForm'which is a Windows Form.
From my DataManger.cs Class, I instantiate the object 'Program.MainFormObj = new MainForm()' and then call the Show method in order to display my Form. It looked like the the Paint event for the form doesn't get to finish but it does kick off as some controls are drawn. Presumably because the main thread (this is all running on one the main thread) is 'occupied' by the next statement. I figured, regardless of known problems I'd use Application.DoEvents() to temporarily counter this issue. As I imagined, it worked, but only to a certain extent. If I put a blocking method like MessageBox.Show(), I can view my completely flawless form in the background but as soon as I press 'OK' and the code proceeds the entire application exits.
I'm really stuck. Despite some extensive searching both here and using Google I can't find an apporpiate answer. I did this this thread: Form.Show() is not showing it's child controls but the given solution isn't appropriate for my solution. Any help is appreciated very much, thanks.
Upvotes: 2
Views: 2911
Reputation: 150228
If this is a large project, invest time now to refactor it.
Fighting the way WinForms works will be much more expensive in the mid-term than investing time now to do things right.
If you have any choice about the technology, consider WPF instead. There is a learning curve with WPF, but it may well be worth investing in that learning now.
UPDATE
Based on your code sample, I see that you are probably creating some of your forms on a thread other than the main UI thread. While that is allowed, it creates for very confusing code because forms can only be updated from the thread they were created on.
The simplest hack to get this working is probably to update HandleIncomingData
to also invoke the Show()
calls on the main UI thread.
There is supposed to be a way to cleanly do that from a static method, outlined here:
https://stackoverflow.com/a/505361/141172
However, when I tried that, I found that SynchronizationContext
was always null. I'm sure I'm just missing a step.
I was able to get things working by misusing the LoginForm
(assuming, perhaps incorrectly, that the form is always available. If not, perhaps create a special form just for thread marshaling).
The hack looks like this:
Program.MainForm = new MainForm();
try
{
MessageBox.Show("Login Success.", "Login", MessageBoxButtons.OK, MessageBoxIcon.Information);
// Abusing LoginForm's Invoke method. Code assumes LoginForm is always available.
Program.LoginForm.Invoke((MethodInvoker)delegate
{
Program.MainForm.Show();
});
}
catch (Exception Ex)
{
MessageBox.Show(Ex.ToString()); //Debuging purposes
}
By the way, there's an excellent extension method that makes it a breeze to invoke UI code from a non-UI thread:
https://stackoverflow.com/a/3588137/141172
Upvotes: 2