我无法两次关闭窗体,在创建窗口句柄之前无法在控件上调用Invoke或BeginInvoke [英] I can not close a form twice, Invoke or BeginInvoke cannot be called on a control until the window handle has been created

查看:64
本文介绍了我无法两次关闭窗体,在创建窗口句柄之前无法在控件上调用Invoke或BeginInvoke的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


当用户选择菜单项时,我将从主窗体中打开一个如下所示的窗体.

Hi
I''m opening a form as shown below from my main form when the user makes a selection of a menu item.

private void commToolStripMenuItem_Click(object sender, EventArgs e)
            {
                Command_Form Command_Form1 = new Command_Form();
                Command_Form1.ShowDialog();
               // Command_Form1.Dispose();    this didn''t help
            }

在"Command_Form1"表格内
当用户单击关闭按钮时,我会像这样关闭它

Inside the form "Command_Form1"
I close it like this when the user clicks on the close button

private void Close_button_Click(object sender, EventArgs e)
          {
            this.Close();    //I get the exception here
          }

此过程可以正常运行一次,但要在表单的第二次关闭时有效
(我希望这是表单的完全不同/新实例)我在这篇文章的标题中遇到了错误.
这是调试窗口中的输出.
* System.Windows.Forms.dll中发生了类型为"System.InvalidOperationException"的第一次机会异常*
列出此错误的所有主题继续进行,关于不尝试对未显示的表单执行任何操作,但是当我单击表单中的按钮时,就会发生这种情况.
在我看来,如果我能够单击表单的按钮,几乎可以确保该表单已显示.
我发现的其他帖子都列出了此类错误,继续进行线程安全调用,因此我尝试将其作为实验,但没有任何区别.

This process works fine once but on the second closing of the form
(Which I hope is a completely different/new instance of the form) I get the error in the title of this post.
This is the output in the debug window.
*A first chance exception of type ''System.InvalidOperationException'' occurred in System.Windows.Forms.dll*
All the topics that list this error go on about not trying to do anything to a form that has not been displayed but this happens when I click on a button in the form.
It would seem to me that pretty much ensures the form has been displayed if I''m able to click its button.
The other posts I''ve found that list this type of error go on about making thread safe calls so I tried this as an experiment but it didn''t make any difference.

private void Close_button_Click(object sender, EventArgs e)
               {
       if (this.InvokeRequired)
                   {
                       CloseCallback d = new CloseCallback(Close_button_Click);
                       Invoke(d, new object[] { sender, e });
                   }
                   else
                   {
                       this.Close();

我的应用程序中有多个线程,但是它们是由我使用的控件创建的,而不是由我明确使用的.
我正在通过代理将接收/发送的数据封送处理,从而将数据从串行端口传递到表单,或从表单传递数据.
有意义的是,串行端口将在与表单不同的线程上运行,但是为什么单击表单的按钮与表单在不同的线程上呢? 整个线程很混乱
如何找出未明确创建的线程中的线程起源和发生的事情?
为什么我需要通过委托来调用表单的close方法?
哎呀,在这种多线程环境中,我可以做些安全的事情,如果我不知道创建线程的位置/原因/原因/原因/原因,我该怎么做才是不安全的? ?

I have multiple threads in my application but they are created by the controls I''m using not by me explicitly.
I am passing data from a serial port to/from the form by Marshling the received/sent data via a delegate[s].
It makes sense that the serial port would run on a different thread than the form but why would a button click on a form be in a diffrent thread than the form????
The whole thread thing is very confuzing
How do I figure out what threads originated where and what is going on in the threads that I didn''t create explicitly?
Why would I need to invoke the form''s close method via a delegate?
Heck is there anything I can do in this multi threading environment that is thread safe How do I know if what I''m doing is unsafe/safe if I don''t know what/where/why/who/when is creating threads?

推荐答案

尝试一下(不保证):

Try this (no guarantees):

public class MyParentForm:Form
{
    private Command_Form Command_Form1 = null; 

    private void commToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Command_Form1 = new Command_Form();
        Command_Form1.Disposed += new EventHandler(cmdForm_Disposed)
        Command_Form1.ShowDialog();
    }

    void myForm_Disposed(object sender, EventArgs e)
    {
        Command_Form1 = null;
    }
}


我不认为您对话框的问题是线程化.该对话框从UI中显示,从UI中关闭,因此不需要Invoke.当然,除了UI之外,您永远都不要操作其他线程的表单.
您需要的是惰性模式.仅创建一次对话框:

I don''t think you problem with the dialog is threading. The dialog is shown from UI and closed from UI, so no Invoke required. Of course you should never operate forms from threads other than UI.

What you need is lazy pattern. Create you dialog only once:

class MyClass /* ... */ { //can be your main form or something else working as a signleton

void ShowCommands {
   if (Command_Form1 == null)
      Command_Form1 = new Command_Form();
   Command_Form1.ShowDialog();
   //...
} //ShowCommands

Command_Form Command_Form1; //fixed!

} //MyClass



您唯一需要做的就是覆盖Form.FormClosing,这样对话框不会关闭而是被隐藏了.应将事件参数的Cancel分配给true,以防止真实"关闭,并且该表单应隐藏:



The only step you need is to override Form.FormClosing so the dialog in not closed but got hidden. The event argument''s Cancel should be assigned to true to prevent "real" closing, and the form should by hidden:

Command_Form1.FormClosing += (sender, eventArg) => {
    eventArg.Cancel = true;
    Command_Form1.Hide();
}; //Command_Form1.FormClosing



这种方法的好处是,对话框始终处于最新状态:控件属性,选择,集中控件等,这对用户来说更加方便.

—SA



The bonus effect of such approach is that you always have you dialog form in the most recent state: control property, selection, focused control, etc., which is more convenient for the user.

—SA


你好朋友..
如您所言,您是通过委托将接收/发送的数据封送处理,从而将数据从串行端口传递到表单或从表单传递出去.在这里,您已经打开了端口,但是没有关闭端口.这就是为什么当您尝试第二次打开它时,它会打开并在关闭时生成错误.
您想要执行的操作,只需关闭Form.Closing()中的端口即可.您的问题将得到解决.
Hello friend..
As u told you are passing data from a serial port to/from the form by Marshling the received/sent data via a delegate[s]. Here, you had open the port, but you did not close the port. Thats why when you try to open it second time, its open and generate the error at the time of closing.
What you want to do, just close the port in Form.Closing(). Your problem will get solved.


这篇关于我无法两次关闭窗体,在创建窗口句柄之前无法在控件上调用Invoke或BeginInvoke的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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