標籤:
對於文章裡面碰到的問題,可能也是我學習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()函數中就能解決了,那這個提供了一個思路,那就是跨線程修改表單內容通過委託就能實現了,我想是這樣的吧,可能由於我能力不足只能作此簡單分析,不足之處往指正。
線程學習筆記2