Invoke or BeginInvoke cannot be called on a control until the window handle has been created

By FoxLearn 3/20/2025 1:32:36 AM   37
In a WinForms project, if you try to call Invoke or BeginInvoke on a control before the window handle has been created, you'll encounter the following exception:
System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created

This issue usually happens when the form is still initializing, and as a result, the form may not appear at all. You would only notice this exception by checking the Windows Event Viewer or running the project in a debugger.

An example scenario is when you're attempting to update a progress bar in the constructor of a form, like so:

public partial class frmMain : Form
{
    ProgressBar progressBar;
    public frmMain()
    {
        InitializeComponent();
        progressBar = new ProgressBar();
        progressBar.Maximum = 100;
        progressBar.Value = 0;
        UpdateProgress(10);
    }

    private void UpdateProgress(int value)
    {
        progressBar.BeginInvoke((MethodInvoker)delegate ()
        {
            progressBar.Value = value;
        });
    }
}

Solution

The error clearly indicates that you cannot call Invoke or BeginInvoke before the window handle is created.

There are two ways to ensure that the window handle has been created:

  1. The OnHandleCreated event has fired.
  2. The this.IsHandleCreated property is true.

Below are two possible solutions to resolve the issue.

Option 1 - Override OnHandleCreated and move your code there

Most likely, you intended to invoke the update while the form is still initializing. The OnHandleCreated event fires after the window handle is created, making it the earliest time to safely call Invoke or BeginInvoke.

public partial class frmMain : Form
{
    ProgressBar progressBar;
    
    public frmMain()
    {
        InitializeComponent();
        progressBar = new ProgressBar();
        progressBar.Maximum = 100;
        progressBar.Value = 0;
        // Do not call BeginInvoke in the constructor
    }

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        UpdateProgress(10); // Safe to call here
    }

    private void UpdateProgress(int value)
    {
        progressBar.BeginInvoke((MethodInvoker)delegate ()
        {
            progressBar.Value = value;
        });
    }
}

Option 2 - Check if the window handle is created before calling Invoke/BeginInvoke

If you just want to eliminate the error and proceed with updating the control only if the handle is created, you can check the this.IsHandleCreated property before calling Invoke or BeginInvoke:

public partial class frmMain : Form
{
    ProgressBar progressBar;
    
    public frmMain()
    {
        InitializeComponent();
        progressBar = new ProgressBar();
        progressBar.Maximum = 100;
        progressBar.Value = 0;
        UpdateProgress(10);
    }

    private void UpdateProgress(int value)
    {
        if (this.IsHandleCreated)
        {
            progressBar.BeginInvoke((MethodInvoker)delegate ()
            {
                progressBar.Value = value;
            });
        }
    }
}

This approach solves the issue by ensuring that you're only trying to invoke or begin invoking after the window handle has been created, preventing the InvalidOperationException from being thrown.