简体   繁体   English

从调用内部关闭表格

[英]Closing Form from inside an Invoke

Closing a form from inside an Invoke like this: 从这样的Invoke内部关闭表单:

Invoke(new Action(() => {
    Close();
    MessageBox.Show("closed in invoke from another thread");
    new Form1();
}));

throws an exception as soon as the form is closed: 关闭表单后立即引发异常:

Invoke or BeginInvoke cannot be called on a control until the window handle has been created. 在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke。

But only on NET 4.0. 但仅在NET 4.0上。 On NET 4.5 no exceptions are thrown. 在NET 4.5上,不会引发任何异常。

Is this expected behavior? 这是预期的行为吗? How should I go about it? 我应该怎么做?

If you start a thread during initialisation, you do not know how far the initialisation has gone in another thread. 如果在初始化期间启动线程,则不知道初始化在另一个线程中进行了多长时间。

You notice differences in behavior on different .Net versions, but you cannot be sure about the order of things on different machines. 您会注意到不同.Net版本在行为上的差异,但是您无法确定不同计算机上事物的顺序。

I have solved a lot of threading issues in Windows forms using my own messagepump, using a Queue and a normal Timer control: 我已经使用自己的messagepump,队列和常规Timer控件解决了Windows窗体中的许多线程问题:

  • Add a timer control to your form, with a small interval (250 ms) 将计时器控件添加到窗体中,间隔很小(250毫秒)
  • Add a Queue to your form. 将队列添加到您的窗体。
  • Let the timer event dequeue the actions, and execute it. 让timer事件使动作出队并执行它。
  • Add Actions to the queue during initialisation or even other background jobs. 在初始化甚至其他后台作业期间将操作添加到队列中。

Using this approach will issues with background jobs during initialisation, but also during closing/disposing of the form, since the timer will only trigger if the form is fully functional. 使用此方法将在初始化期间以及在关闭/处置表单期间给后台作业带来问题,因为计时器仅在表单完全起作用时才会触发。

That's because Close method closes the form and destroys it's handle and then the MessageBox is invoked in the Closed form with no handle, so the error message shows up. 这是因为Close方法关闭了窗体并破坏了它的句柄,然后在没有句柄的Closed窗体中调用了MessageBox,因此显示了错误消息。

I don't understand your purpose, but you should either move the code after Close out of invoke, or move the Close after them. 我不明白您的目的,但是您应该在“关闭”之后将代码移出调用,或者将“关闭”移到它们之后。 For example: 例如:

Invoke(new Action(() => {
    Hide();
    MessageBox.Show("closed in invoke from another thread");
    new Form1();
    Close();
}));

Edit: 编辑:

MSDN note about Control.Invoke : 有关Control.Invoke的 MSDN注意:

The Invoke method searches up the control's parent chain until it finds a control or form that has a window handle if the current control's underlying window handle does not exist yet. 如果当前控件的基础窗口句柄尚不存在,则Invoke方法将向上搜索控件的父链,直到找到具有窗口句柄的控件或窗体。 If no appropriate handle can be found, the Invoke method will throw an exception. 如果找不到合适的句柄,则Invoke方法将引发异常。 Exceptions that are raised during the call will be propagated back to the caller. 呼叫期间引发的异常将传播回呼叫者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM