C#编译错误:"调用或BeginInvoke可直到窗口句柄已创建不能在控制称为QUOT; [英] C# compile error: "Invoke or BeginInvoke cannot be called on a control until the window handle has been created."

查看:3713
本文介绍了C#编译错误:"调用或BeginInvoke可直到窗口句柄已创建不能在控制称为QUOT;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚发布了关于如何获得一个委托更新另一个窗体上的文本框的问题。就在我以为我已经使用调用的答案......发生这种情况。这里是我的代码:



主要表单代码:



 使用系统; 
使用System.Drawing中; System.Collections中使用
;
使用System.ComponentModel;使用System.Windows.Forms的
;
使用System.Data这;
:使用System.IO;
使用System.Data.OleDb;
使用System.Collections.Specialized;
使用System.Text;
使用的System.Threading;

委托无效logAdd(字符串消息);

命名空间LCR_ShepherdStaffupdater_1._0
{
公共部分类主营:表
{
公众的Main()
{
的InitializeComponent ();
}

公共无效添加(字符串消息)
{
this.Log.Items.Add(消息);
}
公共无效logAdd(字符串消息)
{///////////////////////////编译器错误BELOW ///////////
this.Invoke(新logAdd(添加),新的对象[] {消息});这里发生//编译错误
} //////////////////////////////编译器错误高于////// /////

私人无效exitProgramToolStripMenuItem_Click(对象发件人,EventArgs五)
{
Application.Exit();
}
私人无效aboutToolStripMenuItem1_Click(对象发件人,EventArgs五)
{
组成AboutBox的=新AboutBox1();
aboutBox.ShowDialog();
}

私人无效settingsToolStripMenuItem_Click(对象发件人,EventArgs五)
{
}

私人无效settingsToolStripMenuItem1_Click(对象发件人,EventArgs的)
{
settingsForm.settings.ShowDialog();
}

私人无效synchronize_Click(对象发件人,EventArgs五)
{
字符串消息=这里我的消息; //改变了这种
ErrorLogging.updateLog(消息); //改变了这种
}

}

公共类settingsForm
{
公共静态表格设置=新设置();
}

}



日志记录类代码:

 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;

命名空间LCR_ShepherdStaffupdater_1._0
{
公共类记录
{
静态Main mainClass =新的Main();
静态logAdd logAddDelegate;

公共静态无效updateLog(字符串消息)
{
logAddDelegate = mainClass.logAdd;
logAddDelegate(消息);
}
}
}




  • 编译错误:



    出现InvalidOperationException是
    未处理 - 调用或BeginInvoke
    不能被称为在控制,直到
    的窗口句柄已创建。




我已经尝试过创建日志项的处理......但没有奏效。问题是我不知道我在做什么,我已搜查谷歌的广泛才发现含糊不清的答案。



请告诉我如何创建句柄之前我调用此委托。当你在这,给我一些方法,我可以使此代码更简单。例如,我不想要两个添加功能...我不得不这样做,因为没有办法,我找到了记录类调用的项目。有没有更好的方式来完成我需要做什么?



感谢您!



编辑:



我的项目是相当大的,但这些都是造成这一特定问题的唯一项目



登录是我RichTextBox1(Log.Items.Add(消息))我重新命名为日志,以便更容易重新输入。



我从不同的形式调用updateLog(消息),但...让我更新,在这里(虽然它没有什么区别,我称之为updateLog(消息)从它仍然给我这个错误)



你们将不得不使事情变得更加简单,对我来说...并提供了示例。我不明白你们在说这里的一切的一半...我有关于如何使用的方法和中调用句柄的工作毫无头绪。我研究屁滚尿流太...



第二编辑:



我相信我已经找到了问题,但不知道如何解决它。



在我的日志类我用这个代码来创建mainClass:



静态Main mainClass =新的Main();



我创建一个全新的蓝图副本主(),其中的登录(我试图更新的RichTextBox)



当我打电话updateLog(消息),我相信我试图在主要的()中的第二实体否则称为mainClass更新的日志(RichTextBox中)。当然,这样做会抛出我这个例外,因为我还没有看到,我采用了目前主流的该副本。



这是我所拍摄的,由于这给了一个答案的人之一:

 主要mainClass = Application.OpenForms.OfType<主>()第一(); 
logAddDelegate = mainClass.logAdd;
logAddDelegate(消息);



我需要创建mainClass不能以新的()运算符,因为我不想创建新蓝图形式我希望能够编辑当前窗体。



上面的代码不工作,虽然,我甚至无法找到应用。是,即使是C#语法?



如果我能得到上面的代码工作,我想我可以解决我的问题,最后打下这个问题的几个小时后要休息,寻求答案



最后编辑:



我想通了谢谢下面的用户之一。这是我更新的代码:



主要表单代码:



 使用系统; 
使用System.Drawing中; System.Collections中使用
;
使用System.ComponentModel;使用System.Windows.Forms的
;
使用System.Data这;
:使用System.IO;
使用System.Data.OleDb;
使用System.Collections.Specialized;
使用System.Text;
使用的System.Threading;

委托无效logAdd(字符串消息);

命名空间LCR_ShepherdStaffupdater_1._0
{
公共部分类主营:表
{
私有静态主要mainFormForLogging;
公共静态主MainFormForLogging
{
得到
{
返回mainFormForLogging;
}
}

公众的Main()
{
的InitializeComponent();
如果(mainFormForLogging == NULL)
{
mainFormForLogging =这一点;
}
}

公共无效添加(字符串消息)
{
this.Log.Items.Add(消息);
}
公共无效logAdd(字符串消息)
{
this.Log.BeginInvoke(新logAdd(添加),新的对象[] {消息});
}

私人无效exitProgramToolStripMenuItem_Click(对象发件人,EventArgs五)
{
Application.Exit();
}
私人无效aboutToolStripMenuItem1_Click(对象发件人,EventArgs五)
{
组成AboutBox的=新AboutBox1();
aboutBox.ShowDialog();
}

私人无效settingsToolStripMenuItem_Click(对象发件人,EventArgs五)
{
}

私人无效settingsToolStripMenuItem1_Click(对象发件人,EventArgs的)
{
settingsForm.settings.ShowDialog();
}

私人无效synchronize_Click(对象发件人,EventArgs五)
{
加(测试);
Logging.updateLog(testthisone);
//DatabaseHandling.createDataSet();
}

}

公共类settingsForm
{
公共静态表格设置=新设置();
}

}



日志记录类代码:

 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;

命名空间LCR_ShepherdStaffupdater_1._0
{
公共类记录
{

静态Main mainClass = Main.MainFormForLogging;
静态logAdd logAddDelegate;

公共静态无效updateLog(字符串消息)
{
logAddDelegate = mainClass.logAdd;
logAddDelegate(消息);
}
}
}


解决方案

右键,我要重新开始。



为了了解发生了什么,你需要了解.NET和Windows之间的相互关系。 .NET运行在Windows和包装的许多人,Win32的概念,就像一个窗口,一个ListView,一个编辑框(Win32命名为一个标准的文本框)。这意味着你可以有一个文本框或表格的一个有效的.NET实例,但没有该项目(编辑框或窗口)的潜在Windows版本呢。当HandleCreated在是真实的,该项目的Windows版本中创建。



您的问题正在发生,因为事情是通往logAdd方法已创建窗体的窗口之前被称为。 Form实例被实例化后,但已创建窗口句柄之前的东西试图调用logAdd这是你在启动过程中的某个地方的意思。如果添加断点logAdd,你应该能够看到正在做这一呼吁。你会发现是,呼叫正在对您在记录器类中创建,实际上是运行在主实例和不是主要的实例进行。由于记录器实例永远不会被显示,窗口句柄没有创建,让您得到您的错误。



应用程序运行的一般方法是调用Application.Run(新的Main())在你的启动方法,通常是在程序类和一个名为为主。你需要你的记录指向主此实例。



有几种方法可以获取表单的实例,每个都有自己的警告,但为了简化你可以暴露实例关闭主类本身。例如:

 公共部分类主营:表
{
私有静态主要mainFormForLogging;
公共静态主MainFormForLogging
{
得到
{
返回mainFormForLogging;
}
}

公众的Main()
{
的InitializeComponent();

如果(mainFormForLogging == NULL)
{
mainFormForLogging =这一点;
}
}

保护无效的Dispose(BOOL处置)
{
如果如果(这个(处置)
{
== mainFormForLogging)
{
mainFormForLogging = NULL;
}
}

base.Dispose(处置);
}
}


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:

Main Form Code:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Data.OleDb;
using System.Collections.Specialized;
using System.Text;
using System.Threading;

delegate void logAdd(string message);

namespace LCR_ShepherdStaffupdater_1._0
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();
        }

        public void add(string message)
        {
            this.Log.Items.Add(message);
        }
        public void logAdd(string message)
        {   /////////////////////////// COMPILER ERROR BELOW ///////////
            this.Invoke(new logAdd(add), new object[] { message }); // Compile error occurs here     
        }////////////////////////////// COMPILER ERROR ABOVE ///////////

        private void exitProgramToolStripMenuItem_Click(object sender, EventArgs e) 
        {
            Application.Exit(); 
        }
        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Form aboutBox = new AboutBox1(); 
            aboutBox.ShowDialog(); 
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void settingsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            settingsForm.settings.ShowDialog();
        }

        private void synchronize_Click(object sender, EventArgs e)
        {
            string message = "Here my message is"; // changed this
            ErrorLogging.updateLog(message);  // changed this
        }

    }

    public class settingsForm 
    {
        public static Form settings = new Settings();
    }

}

Logging Class Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LCR_ShepherdStaffupdater_1._0
{
    public class Logging
    {
        static Main mainClass = new Main();
        static logAdd logAddDelegate;

        public static void updateLog(string message)
        {
            logAddDelegate = mainClass.logAdd;
            logAddDelegate(message);
        }
    }
}

  • Compile Error:

    InvalidOperationException was unhandled - Invoke or BeginInvoke cannot be called on a control until the window handle has been created.

I already tried to create a handle on the Log item...but that didn't work. The problem is I have NO CLUE what I am doing and I have searched Google extensively only to find vague answers.

Please tell me how to create the handle before I invoke this delegate. While you are at it, give me some ways I can make this code more simple. For example, I dont want two Add functions... I had to do that because there was no way for me to find an item to invoke from the Logging class. Is there a better way to accomplish what I need to do?

Thank you!!!

EDIT:

My project is fairly large, but these are the only items causing this specific problem.

Log is my RichTextBox1 (Log.Items.Add(message)) I renamed it to Log so it is easier to retype.

I am calling updateLog(message) from a different form though...let me update that in here (although it makes no difference where I call updateLog(message) from it still gives me this error)

You guys are going to have to make things more simpler for me...and provide examples. I don't understand HALF of everything you guys are saying here...I have no clue on how to work with Invoking of methods and Handles. I've researched the crap out of it too...

SECOND EDIT:

I believe I have located the problem, but do not know how to fix it.

In my logging class I use this code to create mainClass:

static Main mainClass = new Main();

I am creating a entirely new blueprint replica to Main(), including Log (the richtextbox I am trying to update)

When I call updateLog(message) I believe I am trying to update the Log (richtextbox) on the second entity of Main() otherwise known as mainClass. Of course, doing so will throw me this exception because I haven't even seen that replica of the current Main I am using.

This is what I am shooting for, thanks to one of the people that gave an answer:

Main mainClass = Application.OpenForms.OfType<Main>().First();
logAddDelegate = mainClass.logAdd; 
logAddDelegate(message);

I need to create mainClass not with the new() operator because I dont want to create a new blueprint of the form I want to be able to edit the current form.

The above code doesn't work though, I can't even find Application. Is that even C# syntax?

If I can get the above code to work, I think I can resolve my issue and finally lay this problem to rest after a couple of HOURS of seeking for answers.

FINAL EDIT:

I figured it out thanks to one of the users below. Here is my updated code:

Main Form Code:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Data.OleDb;
using System.Collections.Specialized;
using System.Text;
using System.Threading;

delegate void logAdd(string message);

namespace LCR_ShepherdStaffupdater_1._0
{
    public partial class Main : Form
    {
        private static Main mainFormForLogging;
        public static Main MainFormForLogging
        {
            get
            {
                return mainFormForLogging;
            }
        }

        public Main()
        {
            InitializeComponent();
            if (mainFormForLogging == null)
            {
                mainFormForLogging = this;
            }
        }

        public void add(string message)
        {
            this.Log.Items.Add(message);
        }
        public void logAdd(string message)
        {
            this.Log.BeginInvoke(new logAdd(add), new object[] { message });
        }

        private void exitProgramToolStripMenuItem_Click(object sender, EventArgs e) 
        {
            Application.Exit(); 
        }
        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Form aboutBox = new AboutBox1(); 
            aboutBox.ShowDialog(); 
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void settingsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            settingsForm.settings.ShowDialog();
        }

        private void synchronize_Click(object sender, EventArgs e)
        {
            add("test");
            Logging.updateLog("testthisone");
            //DatabaseHandling.createDataSet();
        }

    }

    public class settingsForm 
    {
        public static Form settings = new Settings();
    }

}

Logging Class Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LCR_ShepherdStaffupdater_1._0
{
    public class Logging
    {

        static Main mainClass = Main.MainFormForLogging;
        static logAdd logAddDelegate;

        public static void updateLog(string message)
        {
            logAddDelegate = mainClass.logAdd;
            logAddDelegate(message);
        }
    }
}

解决方案

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);
    }
}

这篇关于C#编译错误:&QUOT;调用或BeginInvoke可直到窗口句柄已创建不能在控制称为QUOT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆