C#实现在线程中打开新窗体 线程结束后,资源被回收,自动窗体关闭

 C#实现在线程中打开新窗体    在线程中建的窗体,所有的资源都是属于这个线程的,所以当这个线程结束后,它的资源也被回收了,当然C#也就自动把窗体给关闭了

http://blog.csdn.net/dangercheng/article/details/8205009

最近做个Winform程序,就避免不到多窗体的应用,我在着里面自然也就产生了许多疑惑。首先,我们们在主窗体中点击一个按钮打开一个新窗体时,这个新窗体是否是一个新的线程中打开的呢?于是做个试验测试代码如下:

Form.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.Threading;  
  10.   
  11. namespace Test  
  12. {  
  13.     public partial class Form1 : Form  
  14.     {  
  15.         public Form2 f2;  
  16.         public Form1()  
  17.         {  
  18.             InitializeComponent();  
  19.         }  
  20.           
  21.         private void Form1_Load(object sender, EventArgs e)  
  22.         {  
  23.             int threadId = Thread.CurrentThread.ManagedThreadId;  
  24.             textBox1.Text = threadId.ToString(); //将主线程ID显示在文本框中  
  25.             f2 = new Form2();   
  26.         }  
  27.   
  28.         private void button1_Click(object sender, EventArgs e)  
  29.         {  
  30.             f2.Show();//显示Form2  
  31.         }  
  32.     }  
  33. }  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Test
{
    public partial class Form1 : Form
    {
        public Form2 f2;
        public Form1()
        {
            InitializeComponent();
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            textBox1.Text = threadId.ToString(); //将主线程ID显示在文本框中
            f2 = new Form2(); 
        }

        private void button1_Click(object sender, EventArgs e)
        {
            f2.Show();//显示Form2
        }
    }
}

Form2.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.Threading;  
  10.   
  11. namespace Test  
  12. {  
  13.     public partial class Form2 : Form  
  14.     {  
  15.         int i = 1;  
  16.         public Form2()  
  17.         {  
  18.             InitializeComponent();  
  19.         }  
  20.   
  21.         private void Form2_Load(object sender, EventArgs e)  
  22.         {  
  23.             MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());//弹出显示当前线程      
  24.         }  
  25.     }  
  26. }  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Test
{
    public partial class Form2 : Form
    {
        int i = 1;
        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());//弹出显示当前线程    
        }
    }
}

运行结果:

很明显,都是在10号线程中运行的,但是现在有个问题出现了,假如,我们在Form1中读一个文本文件的同时Form2中对此文本文件进行写操作,那会冲突吗?这个还有待做实验验证了,在此省略了。

 

接下在线程中打开Form2

Form1.cs代码如下

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.Threading;  
  10.   
  11. namespace Test  
  12. {  
  13.     public partial class Form1 : Form  
  14.     {  
  15.         public Form2 f2;  
  16.         public Form1()  
  17.         {  
  18.             InitializeComponent();  
  19.         }  
  20.           
  21.         private void Form1_Load(object sender, EventArgs e)  
  22.         {  
  23.             int threadId = Thread.CurrentThread.ManagedThreadId;  
  24.             textBox1.Text = threadId.ToString(); //将主线程ID显示在文本框中  
  25.             f2 = new Form2();   
  26.         }  
  27.   
  28.         private void button1_Click(object sender, EventArgs e)  
  29.         {  
  30.             Thread thread2 = new Thread(threadPro);//创建新线程  
  31.             thread2.Start();  
  32.         }  
  33.         public void threadPro()  
  34.         {  
  35.             f2.Show();  
  36.         }  
  37.     }  
  38. }  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Test
{
    public partial class Form1 : Form
    {
        public Form2 f2;
        public Form1()
        {
            InitializeComponent();
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            textBox1.Text = threadId.ToString(); //将主线程ID显示在文本框中
            f2 = new Form2(); 
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread2 = new Thread(threadPro);//创建新线程
            thread2.Start();
        }
        public void threadPro()
        {
            f2.Show();
        }
    }
}

Form2.cs的代码不变

运行程序结果如下:

 

可以看到,两个窗体现在在不同的线程中了,但是我们点击确定后Form2窗体总是一闪而过就没有了,这是什么原因呢?这是因为在线程中建的窗体,所有的资源都是属于这个线程的,所以当这个线程结束后,它的资源也被回收了,当然C#也就自动把窗体给关闭了。

这里就需要对Form1.cs就行如下修改:

 

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.Threading;  
  10.   
  11. namespace Test  
  12. {  
  13.     public partial class Form1 : Form  
  14.     {  
  15.         public Form1()  
  16.         {  
  17.             InitializeComponent();  
  18.         }  
  19.           
  20.         private void Form1_Load(object sender, EventArgs e)  
  21.         {  
  22.             int threadId = Thread.CurrentThread.ManagedThreadId;  
  23.             textBox1.Text = threadId.ToString(); //将主线程ID显示在文本框中  
  24.         }  
  25.   
  26.         private void button1_Click(object sender, EventArgs e)  
  27.         {  
  28.             Thread thread2 = new Thread(threadPro);//创建新线程  
  29.             thread2.Start();  
  30.         }  
  31.         public void threadPro()  
  32.         {  
  33.              MethodInvoker MethInvo = new MethodInvoker(ShowForm2);  
  34.              BeginInvoke(MethInvo);  
  35.         }  
  36.         public void ShowForm2()  
  37.         {  
  38.             Form2 f2 = new Form2();  
  39.             f2.Show();  
  40.         }  
  41.     }  
  42. }  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            textBox1.Text = threadId.ToString(); //将主线程ID显示在文本框中
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread2 = new Thread(threadPro);//创建新线程
            thread2.Start();
        }
        public void threadPro()
        {
             MethodInvoker MethInvo = new MethodInvoker(ShowForm2);
             BeginInvoke(MethInvo);
        }
        public void ShowForm2()
        {
            Form2 f2 = new Form2();
            f2.Show();
        }
    }
}

Form2代码不变,运行结果如下:

点击确定后Form2出现了,也不闪了,但是我们都看到一个问题,那就是两个窗体的在一个线程中,我们不是新建了一个线程吗?这是怎么回事?我的理解是代码中的MethodInvoker其实相当于一个委托,把它作为参数传递给BeginInvoke(MethInvo);执行,而BeginInvoke方法是在Control的线程上执行的,也就是我们平时所说的UI线程,也就是我们的主线程所以就解释了为什么都是10, 那如果我们想不在一个线程中怎么办呢?我能力不够,实在不知道,麻烦知道的告诉一声。

 

我们再对上面的程序进行扩展,那么就会解决一个问题,那就是子线程修改主线程的控件属性的问题。我们首先来看这个问题的存在如下

继续修改Form1.cs的代码,将我们创建的线程ID显示在Form1的第二个文本框中代码如下:

  

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.Threading;  
  10.   
  11. namespace Test  
  12. {  
  13.     public partial class Form1 : Form  
  14.     {  
  15.         public Form1()  
  16.         {  
  17.             InitializeComponent();  
  18.         }  
  19.           
  20.         private void Form1_Load(object sender, EventArgs e)  
  21.         {  
  22.             int threadId = Thread.CurrentThread.ManagedThreadId;  
  23.             textBox1.Text = threadId.ToString(); //将主线程ID显示在文本框中  
  24.         }  
  25.   
  26.         private void button1_Click(object sender, EventArgs e)  
  27.         {  
  28.             Thread thread2 = new Thread(threadPro);//创建新线程  
  29.             thread2.Start();  
  30.         }  
  31.         public void threadPro()  
  32.         {  
  33.             textBox2.Text = Thread.CurrentThread.ManagedThreadId.ToString();  
  34.              MethodInvoker MethInvo = new MethodInvoker(ShowForm2);  
  35.              BeginInvoke(MethInvo);  
  36.         }  
  37.         public void ShowForm2()  
  38.         {  
  39.             Form2 f2 = new Form2();  
  40.             f2.Show();  
  41.         }  
  42.     }  
  43. }  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {
            int threadId = Thread.CurrentThread.ManagedThreadId;
            textBox1.Text = threadId.ToString(); //将主线程ID显示在文本框中
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread2 = new Thread(threadPro);//创建新线程
            thread2.Start();
        }
        public void threadPro()
        {
            textBox2.Text = Thread.CurrentThread.ManagedThreadId.ToString();
             MethodInvoker MethInvo = new MethodInvoker(ShowForm2);
             BeginInvoke(MethInvo);
        }
        public void ShowForm2()
        {
            Form2 f2 = new Form2();
            f2.Show();
        }
    }
}

运行程序,点击按钮1,会报错如下:

 
原来是不能跨线程调用Window窗体控件;很简单我们将textBox2.Text = Thread.CurrentThread.ManagedThreadId.ToString();一道ShowForm2()函数中就能解决了,那这个提供了一个思路,那就是跨线程修改窗体属性通过委托就能实现了,我想是这样的吧,可能由于我能力不足只能作此简单分析,不足之处往指正。

posted @ 2017-06-24 16:12  sky20080101  阅读(1995)  评论(0)    收藏  举报