C#在System.Windows.Forms.Timer的Tick事件中调用Form.Close()方法的怪异问题,想不明白了,请大家帮忙~~

时间:2021-07-16 20:35:26
先描述一下问题,新建个Form的工程(我建的是CF3.5的),在Form中放一个Button控件,一个Timer控件(是这个System.Windows.Forms.Timer),默认设定Timer的Enabled属性为false,Interval属性为3000,其余属性都是默认 。
请看代码一,如下:

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Close();
            timer1.Enabled = false;
        }

点击Button后,关闭该Form,没有任何问题。
怪异的地方在这,请耐心看代码二,如下:

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
            MessageBox.Show("TestText", "TestCaption");
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            IntPtr messageBoxHandle = WindowsAPI.FindWindow(null, "TestCaption");
            if (null != messageBoxHandle)
            {
                WindowsAPI.SendMessage(messageBoxHandle, WindowsAPI.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
            }

            Close();
            timer1.Enabled = false;
        }

关闭Form的Close()方法就不起作用了。
补充说明:FindWindow,SendMessage都是Win32API,另外我也将SendMessage替换成PostMessage试过了,Close()还是无效。
百思不得其解,恳请各位帮忙~~~

20 个解决方案

#1


 MessageBox.Show("TestText", "TestCaption");

在关闭这个MessageBox前,主窗体的消息泵处于阻塞状态,估计“Close();”发出的关闭窗体消息是处理不了
问题应该是出用WM_CLOSE关不了这个MessageBox,发个Enter按键消息试试

#2


非常感谢楼上的回答。不过我还没想清楚,理由如下:
我使用的是SendMessage,消息被处理后才会返回,处理之后,MessageBox应该已经被关闭了的。按照你的分析,消息泵此时应不是阻塞状态了,然后才调用的Close()方法。

#3


有调试,执行到timer1_Tick()里面了吗?

不太清楚c#里面的Timer控件是怎么实现的,如果也是以WM_Timer消息实现的,那程序消息循环直接阻塞在button1_Click()里面了,都执行不到timer1_Tick()里面

另外根据我对MFC的了解来推测:用WM_CLOSE关闭模态窗口,会出现很有意思的现象,呵呵
你先试试改成发送一个Enter按键消息看看吧

#4


肯定执行到timer1_Tick里了,而且可以把MessageBox成功关闭,就是Close不了Form,怪异吧。

#5


模拟Enter按键和Esc按键都不行,连MessageBox都关不掉了。

#6


试了一下,PC上的是可以关闭的,PPC上的就不行
楼主抓一下消息看看吧,呵呵

#7


 Close();
 timer1.Enabled = false;
我觉得这里的CLOSE()指代不明确,加个THIS试试

#8


引用 7 楼 java3344520 的回复:
我觉得这里的CLOSE()指代不明确,加个THIS试试

在Form调用成员函数,指代很明确。
况且也加过this试了,现象依旧。

#9


 Close();
 timer1.Enabled = false;

确定运行到Close()来了吗?

试试用Application.Exit() 方法,猜测的,不知道PPC有没有这方法

#10


确定运行到Close()了。
PPC有Application.Exit()这个方法,不过我是希望关闭当前Form,而不是退出程序。

#11


Close(); 
timer1.Enabled = false; 
这两句代码好像顺序反了

#12


也这么试过,还是不行。

#13


自己再顶一下。

#14


看了一下问题描述 ,第一感觉就是想到发送消息 ,句柄是否传对的问题


猜测:先关子window,结果关的是父window
想close父window ,结果子window还没关,就想执行close父window

可能还跟子window是否为模态dialog有关

mobile 上碰到过不关messagbox,仍能关掉其他窗口,但是messagbox隐藏了,其实还是存在的

#15


问题还在啊

建议自建个Dialog换掉这个MessageBox试试
这个MessageBox是个十分诡异的模态窗口,记得以前有发帖子说过这个MessageBox让窗口里的消息顺序都乱套了

#16


嗯,问题还在。
真是想不明白了。

不过想到个办法是可以了。
把Close改成

WindowsAPI.PostMessage(this.Handle, WindowsAPI.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);

关闭倒是可以了。不过自己还没想明白。
希望能有人指点迷津。

#17


消息机制很深奥啊,呵

#18


> Test.exe!Test.Form1.timer1_Tick(object sender = {Interval = 0x00000064}, System.EventArgs e = {System.EventArgs}) Line 41 C#
  System.Windows.Forms.dll!System.Windows.Forms.Timer._WnProc(Microsoft.AGL.Forms.WM wm = WM_TIMER, int wParam = 0x00000000, int lParam = 0x00000000) + 0x19 bytes
  System.Windows.Forms.dll!System.Windows.Forms.ApplicationThreadContext._InternalContextMessages(Microsoft.AGL.Forms.WM wm = WM_TIMER, int wParam = 0x00046924, int lParam = 0x00000000) + 0x51 bytes
  System.Windows.Forms.dll!Microsoft.AGL.Forms.DLG.MessageBox(string wszCaption = "TestCaption", string wszBody = "TestText", System.Windows.Forms.MessageBoxButtons mbtyp = OK, System.Windows.Forms.MessageBoxIcon mbicon = None, System.Windows.Forms.MessageBoxDefaultButton defbtn = Button1, out System.Windows.Forms.DialogResult mbret = None)
  System.Windows.Forms.dll!System.Windows.Forms.MessageBox.Show(string text = "TestText", string caption = "TestCaption", System.Windows.Forms.MessageBoxButtons buttons = OK, System.Windows.Forms.MessageBoxIcon icon = None, System.Windows.Forms.MessageBoxDefaultButton defaultButton = Button1) + 0x12 bytes
  System.Windows.Forms.dll!System.Windows.Forms.MessageBox.Show(string text = "TestText", string caption = "TestCaption")
  Test.exe!Test.Form1.button1_Click(object sender = {Text = "button1"}, System.EventArgs e = {System.EventArgs}) Line 34 C#
  System.Windows.Forms.dll!System.Windows.Forms.Control.OnClick(System.EventArgs e = {System.EventArgs}) + 0x15 bytes
  System.Windows.Forms.dll!System.Windows.Forms.Button.OnClick(System.EventArgs e = {System.EventArgs}) + 0x32 bytes
  System.Windows.Forms.dll!System.Windows.Forms.ButtonBase.WnProc(Microsoft.AGL.Forms.WM wm = WM_BUTTON_NOTIFYCLICKED, int wParam = 0x00000000, int lParam = 0x00000000) + 0x17 bytes
  System.Windows.Forms.dll!System.Windows.Forms.Control._InternalWnProc(Microsoft.AGL.Forms.WM wm = WM_BUTTON_NOTIFYCLICKED, int wParam = 0x00000000, int lParam = 0x00000000) + 0x4 bytes
  System.Windows.Forms.dll!Microsoft.AGL.Forms.EVL.EnterMainLoop(System.IntPtr hwnMain = 0x00110005)
  System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form fm = {Test.Form1}) + 0xf bytes
  Test.exe!Test.Program.Main() Line 16 + 0xa bytes C#
从栈上来看,你这边肯定是因为Messagebox的缘故被堵塞了。

#19


帮顶~

#20


帮顶。。。。。。。。

#1


 MessageBox.Show("TestText", "TestCaption");

在关闭这个MessageBox前,主窗体的消息泵处于阻塞状态,估计“Close();”发出的关闭窗体消息是处理不了
问题应该是出用WM_CLOSE关不了这个MessageBox,发个Enter按键消息试试

#2


非常感谢楼上的回答。不过我还没想清楚,理由如下:
我使用的是SendMessage,消息被处理后才会返回,处理之后,MessageBox应该已经被关闭了的。按照你的分析,消息泵此时应不是阻塞状态了,然后才调用的Close()方法。

#3


有调试,执行到timer1_Tick()里面了吗?

不太清楚c#里面的Timer控件是怎么实现的,如果也是以WM_Timer消息实现的,那程序消息循环直接阻塞在button1_Click()里面了,都执行不到timer1_Tick()里面

另外根据我对MFC的了解来推测:用WM_CLOSE关闭模态窗口,会出现很有意思的现象,呵呵
你先试试改成发送一个Enter按键消息看看吧

#4


肯定执行到timer1_Tick里了,而且可以把MessageBox成功关闭,就是Close不了Form,怪异吧。

#5


模拟Enter按键和Esc按键都不行,连MessageBox都关不掉了。

#6


试了一下,PC上的是可以关闭的,PPC上的就不行
楼主抓一下消息看看吧,呵呵

#7


 Close();
 timer1.Enabled = false;
我觉得这里的CLOSE()指代不明确,加个THIS试试

#8


引用 7 楼 java3344520 的回复:
我觉得这里的CLOSE()指代不明确,加个THIS试试

在Form调用成员函数,指代很明确。
况且也加过this试了,现象依旧。

#9


 Close();
 timer1.Enabled = false;

确定运行到Close()来了吗?

试试用Application.Exit() 方法,猜测的,不知道PPC有没有这方法

#10


确定运行到Close()了。
PPC有Application.Exit()这个方法,不过我是希望关闭当前Form,而不是退出程序。

#11


Close(); 
timer1.Enabled = false; 
这两句代码好像顺序反了

#12


也这么试过,还是不行。

#13


自己再顶一下。

#14


看了一下问题描述 ,第一感觉就是想到发送消息 ,句柄是否传对的问题


猜测:先关子window,结果关的是父window
想close父window ,结果子window还没关,就想执行close父window

可能还跟子window是否为模态dialog有关

mobile 上碰到过不关messagbox,仍能关掉其他窗口,但是messagbox隐藏了,其实还是存在的

#15


问题还在啊

建议自建个Dialog换掉这个MessageBox试试
这个MessageBox是个十分诡异的模态窗口,记得以前有发帖子说过这个MessageBox让窗口里的消息顺序都乱套了

#16


嗯,问题还在。
真是想不明白了。

不过想到个办法是可以了。
把Close改成

WindowsAPI.PostMessage(this.Handle, WindowsAPI.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);

关闭倒是可以了。不过自己还没想明白。
希望能有人指点迷津。

#17


消息机制很深奥啊,呵

#18


> Test.exe!Test.Form1.timer1_Tick(object sender = {Interval = 0x00000064}, System.EventArgs e = {System.EventArgs}) Line 41 C#
  System.Windows.Forms.dll!System.Windows.Forms.Timer._WnProc(Microsoft.AGL.Forms.WM wm = WM_TIMER, int wParam = 0x00000000, int lParam = 0x00000000) + 0x19 bytes
  System.Windows.Forms.dll!System.Windows.Forms.ApplicationThreadContext._InternalContextMessages(Microsoft.AGL.Forms.WM wm = WM_TIMER, int wParam = 0x00046924, int lParam = 0x00000000) + 0x51 bytes
  System.Windows.Forms.dll!Microsoft.AGL.Forms.DLG.MessageBox(string wszCaption = "TestCaption", string wszBody = "TestText", System.Windows.Forms.MessageBoxButtons mbtyp = OK, System.Windows.Forms.MessageBoxIcon mbicon = None, System.Windows.Forms.MessageBoxDefaultButton defbtn = Button1, out System.Windows.Forms.DialogResult mbret = None)
  System.Windows.Forms.dll!System.Windows.Forms.MessageBox.Show(string text = "TestText", string caption = "TestCaption", System.Windows.Forms.MessageBoxButtons buttons = OK, System.Windows.Forms.MessageBoxIcon icon = None, System.Windows.Forms.MessageBoxDefaultButton defaultButton = Button1) + 0x12 bytes
  System.Windows.Forms.dll!System.Windows.Forms.MessageBox.Show(string text = "TestText", string caption = "TestCaption")
  Test.exe!Test.Form1.button1_Click(object sender = {Text = "button1"}, System.EventArgs e = {System.EventArgs}) Line 34 C#
  System.Windows.Forms.dll!System.Windows.Forms.Control.OnClick(System.EventArgs e = {System.EventArgs}) + 0x15 bytes
  System.Windows.Forms.dll!System.Windows.Forms.Button.OnClick(System.EventArgs e = {System.EventArgs}) + 0x32 bytes
  System.Windows.Forms.dll!System.Windows.Forms.ButtonBase.WnProc(Microsoft.AGL.Forms.WM wm = WM_BUTTON_NOTIFYCLICKED, int wParam = 0x00000000, int lParam = 0x00000000) + 0x17 bytes
  System.Windows.Forms.dll!System.Windows.Forms.Control._InternalWnProc(Microsoft.AGL.Forms.WM wm = WM_BUTTON_NOTIFYCLICKED, int wParam = 0x00000000, int lParam = 0x00000000) + 0x4 bytes
  System.Windows.Forms.dll!Microsoft.AGL.Forms.EVL.EnterMainLoop(System.IntPtr hwnMain = 0x00110005)
  System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form fm = {Test.Form1}) + 0xf bytes
  Test.exe!Test.Program.Main() Line 16 + 0xa bytes C#
从栈上来看,你这边肯定是因为Messagebox的缘故被堵塞了。

#19


帮顶~

#20


帮顶。。。。。。。。

#21