• WinForm的阻塞问题


    很少用WinForm,更别说用两个Form,但没想到,一用就遇到一个不大不小的问题。

    先看一个很简单的例子:一个主Form,TestForm2,在载入的时候Show另一个Form (TestForm3):
    如此之简单,会有什么问题呢?而我的问题是:主Form和它所Show出的另一个Form是什么关系呢?目前的情况是,当我们关闭主Form里,副Form是一定会跟着关闭的,这或许是天经地义的,因为“父窗口”关闭后,子窗口一定得关闭。(暂时定义它们为父子窗口关系吧)

    然而问题是,如果在TestForm里添加一个阻塞线程的函数,那么在主Form退出的时候,子Form没有能一起退出,接下来的问题就是,再退出子Form的时候就会让主进程死在了内存里。
    Forms.JPG
    两个Form的简单代码:
            private void TestForm2_Load(object sender, System.EventArgs e)
            
    {
                
    this.label1.Text    = "Main Form, and ID is:"+this.Handle.ToString();
            }


            
    private void button1_Click(object sender, System.EventArgs e)
            
    {
                TestForm3 m_form        
    = new TestForm3();
                m_form.Show();        
            }
            private void TestForm3_Load(object sender, System.EventArgs e)
            
    {
                
    this.label1.Text    = "Child form and ID is:"+this.Handle.ToString();
            }


            
    private void button1_Click(object sender, System.EventArgs e)
            
    {
                MessageBox.Show(
    "This is a test.");
            }
    注意操作关系:
    1、让主Form(TestForm2)Show一个新的Form(TestForm3)出来。
    2、让新Show出来的TestForm3再Show一个MessageBox来阻塞线程。
    3、退出主Form也就是TestFrom2,此时TestForm3被MessageBox阻塞。
    4、再退出TestForm3,然后观察任务管理器就会发现应该程序的主进程已经死在里面了。

    分析原因:这两个Form一定是多线程关系:
    首先,它们在任务栏里显示的是多个窗口。其次,TestForm3被阻塞的时候,TestForm2可以响应用户操作,最后就是退出时再现的这一现象。

    然而事情也还没有那么简单,如果主Form所Show也来的窗口是一个新的线程,那么我再次Show的时候,应该会产生新的线程,结果是:在任务管理器里,只有3个,不管我再Show多少个窗口出来。。。。。
    而且:System.Threading.Thread.CurrentThread.GetHashCode()所得到的主从窗口是一样的。。。这让我很费解。

    用Syp++查看,结果也让人很郁闷:所有的Form都是同一个进程ID也是同一个线程ID!既然事实是这样的,就没什么好再分析的,接下来的问题是:一个进程,一个线程,它是怎样工作的呢?为什么可以Show一个子Form而不影响主Form呢?也就是说它们完全主像是一个多线程!

    猜测单线程下多Form的工作原理:
    Process.JPG

    因为只有这样才能很好的解释所以遇到的问题:
    因为主线程首先响应主Form,所以它首先得到用户响应。而其它的子Form就会以并列的方式处理。而子Form里的MessageBox的优先级比所有的子Form高,所以在子Form中(不管是哪一个)只要有一个MessageBox出现,它就会阻塞所有的子Form,这与事实相符。
    同样的,根据上面的图示,如果我在主Form里也Show一个MessageBox那么所有的Form都会被阻塞。而实际与是如此。因此这样的工作模式可以解释所遇到的所有问题。
    测试代码:

    Form2
            private void TestForm2_Load(object sender, System.EventArgs e)
            
    {
                
    this.label1.Text    = "Main Form, and ID is:"+this.Handle.ToString();
                
    this.label2.Text    = "ThreadID:"+System.Threading.Thread.CurrentThread.GetHashCode().ToString();
            }


            
    private void button1_Click(object sender, System.EventArgs e)
            
    {
                TestForm3 m_form        
    = new TestForm3();
                m_form.Show();        
            }


            
    private void button2_Click(object sender, System.EventArgs e)
            
    {
                MessageBox.Show(
    "This is a test!");
            }


    Form3
            private void TestForm3_Load(object sender, System.EventArgs e)
            
    {
                
    this.label1.Text    = "Child form and ID is:"+this.Handle.ToString();
                
    this.label2.Text    = "ThreadID:"+System.Threading.Thread.CurrentThread.GetHashCode().ToString();
            }


            
    private void button1_Click(object sender, System.EventArgs e)
            
    {
                MessageBox.Show(
    "This is a test.");
            }

    总结:这并不是一个好的方法来Show窗口,因为这样很让人觉得它是多线程的是,特别是在任务栏上的多窗口,以及MessageBox的阻塞等都很像多线程。。然而事实并非如此。
    这是我偶然遇到的一个问题,实际上如果要处理多窗口,还是应该用多线程,而且也不应该只在一个函数里Show而是应该在全局上处理一下。
  • 相关阅读:
    【翻译自mos文章】rman 标准版和企业版的兼容性
    HDU 1010 Tempter of the Bone
    uva 10716 Evil Straw Warts Live(贪心回文串)
    适配器及适配器模式
    Android推送技术研究
    【hadoop2.6.0】倒排索引遇到问题了
    【hadoop2.6.0】MapReduce原理
    【hadoop2.6.0】一句话形容mapreduce
    【leetcode】Median of Two Sorted Arrays(hard)★!!
    【leetcode】Merge k Sorted Lists
  • 原文地址:https://www.cnblogs.com/WuCountry/p/330289.html
Copyright © 2020-2023  润新知