I have a class that attempts to create an better alternative to the System.Console class. It started as follows:
public class SuperConsole
{
private readonly Form _Form;
public SuperConsole()
{
_Form = new()
{
Text = DefaultTitle,
BackColor = DefaultBackColor,
};
Application.Run(_Form);
}
public string Title
{
get => _Form.Invoke(() => _Form.Text);
set => _Form.Invoke(() => _Form.Text = value);
}
//more stuff
}
Obviously, if I ran the constructor, it would freeze on Application.Run. The form would run, of course, but the caller of the constructor would have to wait a bit. So, I changed the constructor to run Application.Run on a new thread:
public SuperConsole()
{
_Form = new()
{
Text = DefaultTitle,
BackColor = DefaultBackColor,
};
Thread t = new(() => Application.Run(_Form));
t.Start();
}
But this throws a System.InvalidOperationException.
System.InvalidOperationException: 'Invoke or BeginInvoke cannot be called on a control until the window handle has been created.'
I have no idea how to proceed. I have tried several variations to this, to no effect.
I would like both the form and the calling function to be able to run simultaneously, and be able to still use Form.Invoke normally. I also would seek to have the user of the class not have to worry about any of this. How might I do this?
I think that you have to create the
Formon the dedicatedSuperConsolethread, not on the current thread, because UI components are thread-affine. You also have to declare theSuperConsolethread as STA, and wait until the form is created. Something like this should work:The
ManualResetEventSlimis used for signaling that theForminstance has been created, and assigned to the_formfield. Otherwise the current thread could observe the_formto benull.I haven't tested the above code. It is possible that the form might not be ready for calling
Invokebefore the message loop has started. In that case you may have to move themres.Set();inside theHandleCreatedorLoadorShownevent of the form. To learn how to subscribe to an event for one notification only, see this answer.