本文參考yc421206-[C#.NET] 如何 使用 多執行緒 Thread / 跨執行緒 存取UI
本文參考catyku-C# Thread應用
前置動作:
using System.Threading;
Thread三步驟:
1.建立ThreadStart委派
ThreadStart myRun = new ThreadStart(RunSample01);
2.建立Thread類別
Thread myThread = new Thread(myRun);
步驟1.2可以合併為:
Thread myThread = new Thread(new ThreadStart(RunSample01));
3.啟動執行緒
myThread.Start();
將Thread設定為背景執行緒:
myThread.IsBackground = true;
我在寫無窮回圈時,發現按[X]關閉Form,迴圈還是在背景執行,所以到MSDN找到下面的解決方法。
來自MSDN的說明:
執行緒不是背景執行緒就是前景執行緒。
背景執行緒和前景執行緒相同,唯一差別在於背景執行緒不會防止處理序終止。
一旦終止屬於處理序的所有前景執行緒之後,Common Language Runtime 就會結束處理序。
剩下的所有背景執行緒則會在尚未完成之前全部停止。
故解決方法就是,將thread設定為背景執行緒。(如果設定為false,按[X]關閉Form,執行緒仍在背景繼續執行,故要設定為true)
Thread宣告:
public Thread thread1;
可以將thread宣告成Global變數,但是不能在此處new thread,要在function內new thread。
傳值的範例:
private void function() {
threadClass1 obj = new threadClass1("thread1", 10);
thread1 = new Thread(obj.runMe);
thread1.IsBackground = true;
thread1.Start();
}
class要跟form class在同一層
class threadClass1
{
private String title;
private int i;
public thread1(String title, int i)
{
this.title = title;
this.i = i;
}
public void runMe()
{
Console.Write(title + ":開始 \r\n");
System.Threading.Thread.Sleep(1000);
for (int i = 0; i < this.i; i++)
{
Console.Write(title + "\r\n");
System.Threading.Thread.Sleep(2000);
}
Console.Write(title + ":結束 \r\n");
System.Threading.Thread.Sleep(1000);
}
}
用上面的code隨筆寫了一個範例:
按Button時會new thread執行process,thread還沒執行完畢,不允許再new
public Boolean flag=false;
private void button_Click(object sender, EventArgs e)
{
if (flag == false)
{
function();
flag = true;
return;
}
if (thread1.IsAlive) //如果thread 還存在(還沒執行完畢)
{
Console.Write("thread:還沒結束 \r\n");
System.Threading.Thread.Sleep(1000);
}
else
{
function();
}
}
//完整範例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 WindowsFormsApplication1 { public partial class Form1 : Form { public Thread t1,t2,t3; public Boolean flag=false; public Form1() { InitializeComponent(); } private void RunSample01() { Console.WriteLine("建立了一個執行緒{0}", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(1000); } private void RunSample02() { for (int i=0;;i++) { Console.WriteLine("執行緒{0}: 迴圈第{1}次執行", Thread.CurrentThread.ManagedThreadId, i+1); Thread.Sleep(500); } } private void button1_Click(object sender, EventArgs e) { //1.建立ThreadStart委派 //ThreadStart myRun = new ThreadStart(RunSample01); //2.建立Thread 類別 //Thread myThread = new Thread(myRun); //上述兩句可合併 Thread myThread = new Thread(new ThreadStart(RunSample01)); //3.啟動執行緒 myThread.Start(); } private void button2_Click(object sender, EventArgs e) { //1.建立ThreadStart委派 ThreadStart myRun = new ThreadStart(RunSample02); try { //2.建立Thread 類別 Thread myThread = new Thread(myRun); /* 執行緒不是背景執行緒就是前景執行緒。 * 背景執行緒和前景執行緒相同,唯一差別在於背景執行緒不會防止處理序終止。 * 一旦終止屬於處理序的所有前景執行緒之後,Common Language Runtime 就會結束處理序。 * 剩下的所有背景執行緒則會在尚未完成之前全部停止。 */ //設定為背景執行緒(如果設定為false,按[X]關閉Form,執行緒仍在背景繼續執行,故要設定為true。) myThread.IsBackground = true; //3.啟動執行緒 myThread.Start(); } catch (Exception) { //例外 } } private void button3_Click(object sender, EventArgs e) { thread1 obj = new thread1(textBox1.Text,10); Thread t = new Thread(obj.runMe); t.IsBackground = true; t.Start(); } private void button4_Click(object sender, EventArgs e) { thread1 obj = new thread1("擦窗戶",10); t1 = new Thread(obj.runMe); t1.IsBackground = true; t1.Start(); } private void button5_Click(object sender, EventArgs e) { thread1 obj = new thread1("掃地",10); t2 = new Thread(obj.runMe); t2.IsBackground = true; t2.Start(); } private void button6_Click(object sender, EventArgs e) { try { if (t2.IsAlive) //如果thread t2 還存在(還沒執行完畢) { Console.Write("掃地還沒結束不能拖地\r\n"); System.Threading.Thread.Sleep(1000); } else { thread1 obj = new thread1("拖地", 10); t3 = new Thread(obj.runMe); t3.IsBackground = true; t3.Start(); } } catch (Exception) { MessageBox.Show("應該還沒掃地,所以出現錯誤!"); } } private void button7_Click(object sender, EventArgs e) { if (flag == false) { fun(); flag = true; return; } if (t3.IsAlive) //如果thread 還存在(還沒執行完畢) { Console.Write("thread:還沒結束 \r\n"); System.Threading.Thread.Sleep(1000); } else { fun(); } } private void fun() { thread1 obj = new thread1("thread", 10); t3 = new Thread(obj.runMe); t3.IsBackground = true; t3.Start(); } } class thread1 { private String title; private int i; public thread1(String title, int i) { this.title = title; this.i = i; } public void runMe() { Console.Write(title + ":開始 \r\n"); System.Threading.Thread.Sleep(1000); for (int i = 0; i < this.i; i++) { Console.Write(title + "\r\n"); System.Threading.Thread.Sleep(2000); } Console.Write(title + ":結束 \r\n"); System.Threading.Thread.Sleep(1000); } } }