对于文章里面碰到的问题,可能也是我学习1当中出现的问题,新开的线程不管委托与否都在同一个线程里面,所以新线程运行的时候,主窗体也会停住,后来想在新线程中打开窗体的思路来处理,结果碰到下面文章的问题,在多方面的查找和学习后发现有一个办法可以解决它,希望对大家有帮助。
private void button7_Click(object sender, EventArgs e) { Thread thread2 = new Thread(threadPro);//创建新线程 thread2.Start(); } public void threadPro() { Application.Run(new Form10()); //在新线程中用Application Run的方法打开新窗体 } private void Exit_Click(object sender, EventArgs e) { //Application.Exit(); Process.GetCurrentProcess().Kill(); //强制关闭所有进程,用这个代码之前一定要处理完程序正常结束应该保存的数据以及其他操作.. }
参考下面的文章
最近做个Winform程序,就避免不到多窗体的应用,我在着里面自然也就产生了许多疑惑。首先,我们们在主窗体中点击一个按钮打开一个新窗体时,这个新窗体是否是一个新的线程中打开的呢?于是做个试验测试代码如下:
Form.cs
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
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代码如下
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就行如下修改:
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的第二个文本框中代码如下:
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()函数中就能解决了,那这个提供了一个思路,那就是跨线程修改窗体属性通过委托就能实现了,我想是这样的吧,可能由于我能力不足只能作此简单分析,不足之处往指正。