C# compile error: “Invoke or BeginInvoke cannot be called on a control until the window handle has been created.”

前端 未结 9 884
时光取名叫无心
时光取名叫无心 2020-12-16 23:16

I just posted a question about how to get a delegate to update a textbox on another form. Just when I thought I had the answer using Invoke...this happens. Here is my code:<

9条回答
  •  一向
    一向 (楼主)
    2020-12-17 00:08

    Right, I'm going to start again.

    In order to understand what is happening, you need to understand how .NET and Windows relate to one another. .NET runs on Windows and wraps many of the native, Win32 concepts like a window, a listview, an editbox (the Win32 name for a standard textbox). This means that you can have a valid .NET instance of a TextBox or a Form, but not have the underlying Windows version of that item (EditBox, or Window) yet. When HandleCreated is true, the Windows version of the item is created.

    Your issue is occurring because something is leading to the logAdd method being called before the Form's Window has been created. This means somewhere during your startup after the Form instance has been instantiated but before the Window handle has been created, something is trying to call logAdd. If you add a breakpoint to logAdd, you should be able to see what is doing that call. What you will find is that the call is being made on the Main instance you create in your logger class and NOT the Main instance that is actually running. As the logger instance never gets shown, the window handle is not created, and so you get your error.

    The general way an application runs is to call Application.Run(new Main()) in your startup method, which is usually in the Program class and called Main. You need your logger to point to this instance of main.

    There are several ways to get the instance of the form, each with its own caveats, but for simplicity you could expose the instance off the Main class itself. For example:

    public partial class Main : Form
    {
        private static Main mainFormForLogging;
        public static Main MainFormForLogging
        {
            get
            {
                return mainFormForLogging;
            }
        }
    
        public Main()
        {
            InitializeComponent();
    
            if (mainFormForLogging == null)
            {
                mainFormForLogging = this;
            }
        }
    
        protected void Dispose(bool disposing)
        {
             if (disposing)
             {
                 if (this == mainFormForLogging)
                 {
                    mainFormForLogging = null;
                 }
             }
    
             base.Dispose(disposing);
        }
    }
    

提交回复
热议问题