一、知識點介紹
1,更新控件的內容,應該調用控件的Invoke方法。
Invoke指: 在擁有控件的基礎窗口句柄的線程上,用指定的參數列表執行指定委託。該方法接收一個委託類型和委託的參數,因此需要定義委託類型變量,然後傳遞給Invoke方法。
如果其他線程直接調用方法更新控件內容,報錯:線程間操作無效: 從不是創建控件“richTextBox1”的線程訪問它。
2,委託的本質是某一類型的方法,這些方法具有相同的參數和返回類型。
委託類似於C語言中的函數指針,可以指向多個相同類型的函數。
定義委託,只需要在函數返回類型前加上delegate關鍵詞,把函數體大括號{}的內容換成分號即可。比如:
public delegate void DelegateFun(string msg);
DelegateFun就代表了一個函數類型,它接收string參數,返回void。
3,開闢一個線程,直接啓動,後面通過掛起和喚醒實現暫停功能。
Thread t = new Thread(Run);
t.Start(); // 啓動
通過判斷線程狀態,決定是否喚醒線程。
if (t.ThreadState == ThreadState.Suspended) // 如果被掛起了,就喚醒
{
t.Resume();
}
暫停就掛起線程:
t.Suspend(); // 停止,掛起線程
注:也可以定義一個開關,用來控制開始和結束,在開關爲false的時候,直接continue,這樣表現爲暫停輸出,但是實際上線程一直在運行。
二、界面和代碼
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 WindowsFormsApplication3 { public partial class Form2 : Form { public Form2() { InitializeComponent(); } /// <summary> /// 因爲控件的Invoke方法需要接收委託變量,因此需要定義委託和委託變量 /// 定義一個委託,接收一個參數 /// </summary> /// <param name="msg"></param> public delegate void DelegateFun(string msg); /// <summary> /// 定義一個委託變量 /// 這個委託變量,需要初始化指定具體的方法;然後傳遞給控件的Invoke方法調用。 /// </summary> public DelegateFun Fun1; /// <summary> /// 定義一個線程,處理數據,並更新界面 /// </summary> private Thread t = null; // 開始按鈕 private void button1_Click(object sender, EventArgs e) { this.Invoke(Fun1, "開始..."); // 增加判斷,避免每次單擊都開闢一個線程 if (t == null) { t = new Thread(Run); t.Start(); } if (t.ThreadState == ThreadState.Suspended) // 如果被掛起了,就喚醒 { t.Resume(); } } // 結束執行 private void button2_Click(object sender, EventArgs e) { t.Suspend(); // 停止,掛起線程 this.Invoke(Fun1, "...停止"); } // 具體做事情的方法 public void Run() { //...... 處理一些事情,然後輸出日誌 int i = 0; while (true) { i++; // this指Form2 //Invoke指: 在擁有控件的基礎窗口句柄的線程上,用指定的參數列表執行指定委託。 //Invoke的參數是一個委託類型,因此必須定義委託變量 this.Invoke(Fun1, i.ToString()); } } //在form初始化的時候,給委託變量賦值具體的方法 private void Form2_Load(object sender, EventArgs e) { //給委託變量初始化具體的執行方法 Fun1 = Print; } // 輸出日誌的方法 public void Print(string msg) { // 新開闢的線程,不能直接調用這個方法。原因是控件只能由創建它的線程調用。 // 其他線程調用提示錯誤: 線程間操作無效: 從不是創建控件“richTextBox1”的線程訪問它。 this.richTextBox1.AppendText(msg + "\r\n"); this.richTextBox1.ScrollToCaret(); } } }