Problem
In a WinForms project, if you try to call Invoke/BeginInvoke before the window handle is created, you’ll get the following exception:
System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created
Because this exception happens while the form is initializing, it typically results in the form not appearing at all. The only way to see the exception is by looking in Windows Event Viewer or running the project in a debugger.
Your code probably looks something like the code below. The important thing is that it’s calling BeginInvoke() from the constructor.
public partial class frmMain : Form
{
Control control;
public frmMain()
{
InitializeComponent();
control = txtLog;
Log("Initialized");
}
private void Log(string msg)
{
control.BeginInvoke((MethodInvoker)delegate ()
{
txtLog.AppendText(msg);
txtLog.ScrollToCaret();
});
}
}
Code language: C# (cs)
Solution
The error message is clear: you can’t call Invoke/BeginInvoke until the window handle is created. There are two ways to know when the window handle has been created:
- The form event OnHandleCreated() has fired.
- The this.IsHandleCreated property is true.
Therefore, there are two possible solutions. Take a look at the two options below.
Option 1 – Override OnHandleCreated() and move your code there
Most likely you actually intended on calling Invoke/BeginInvoke while the form is initializing.
The OnHandleCreated() event fires after the window handle has been created. You can only call Invoke/BeginInvoke after the window handle has been created. Therefore it makes sense to override OnHandleCreated() and call Invoke/BeginInvoke from there. This is the earliest possible time you can call Invoke/BeginInvoke.
public frmMain()
{
InitializeComponent();
control = txtLog;
//Log("Initialized"); Don't call Invoke/BeginInvoke in the constructor
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
Log("Initialized");
}
private void Log(string msg)
{
control.BeginInvoke((MethodInvoker)delegate ()
{
txtLog.AppendText(msg);
txtLog.ScrollToCaret();
});
}
Code language: C# (cs)
Option 2 – Check if the window handle is created before calling Invoke/BeginInvoke
If you simply want to get rid of the error, check this.IsHandleCreated before calling Invoke/BeginInvoke.
public frmMain()
{
InitializeComponent();
control = txtLog;
Log("Initialized");
}
private void Log(string msg)
{
if (this.IsHandleCreated)
{
control.BeginInvoke((MethodInvoker)delegate ()
{
txtLog.AppendText(msg);
txtLog.ScrollToCaret();
});
}
}
Code language: C# (cs)
Comments are closed.