[C#] 多線程總結(結合進度條)
阿新 • • 發佈:2018-09-17
ali .repo pro 上下文 回調函數 實例 blank type 後臺
線程生命周期
- 未啟動狀態:當線程實例被創建但 Start 方法未被調用時的狀況。
- 就緒狀態:當線程準備好運行並等待 CPU 周期時的狀況。
- 不可運行狀態:
- 已經調用 Sleep 方法
- 已經調用 Wait 方法
- 通過 I/O 操作阻塞
- 死亡狀態:當線程已完成執行或已中止時的狀況。
Thread 常用方法:
- public void Interrupt() 中斷處於 WaitSleepJoin 線程狀態的線程。
- public void Join() 在繼續執行標準的 COM 和 SendMessage 消息泵處理期間,阻塞調用線程,直到某個線程終止為止。
- public void Start() 開始一個線程
- public static void Sleep(int millisecondsTimeout) 讓線程暫停一段時間
一 普通線程
分為兩種,一種是不需要給子線程傳參數,Thread t = new Thread(new ThreadStart(void () target)); 另一種是要給子線程傳一個參數,Thread t = new Thread(new ParameterizedThreadStart(void (object) target));
// 普通線程 private void btn1_Click(object sender, EventArgs e) { progressBar.Value普通線程= 0; Thread tt = new Thread(new ThreadStart(DoWork1)); tt.Name = "不帶參數普通線程"; tt.Start(); Thread t = new Thread(new ParameterizedThreadStart(DoWork2)); t.Name = "帶參數普通線程"; t.IsBackground = true; t.Start(100); _msg += "當前線程的執行狀態:" + t.IsAlive + "\r\n"; _msg += "當前托管線程的唯一標識:" + t.ManagedThreadId + "\r\n"; _msg += "線程名稱:" + t.Name + "\r\n"; _msg += "當前線程的狀態:" + t.ThreadState; MessageBox.Show("消息:\r\n" + _msg, "提示", MessageBoxButtons.OK); } // 線程方法 private void DoWork1() { for (int i = 0; i < 100; i++) { // 跨線程訪問 UI,BeginInvoke 采用異步委托 progressBar.BeginInvoke(new EventHandler((sender, e) => { progressBar.Value = i; }), null); } } // 線程方法 private void DoWork2(object obj) { for (int i = 0; i < (int)obj; i++) { progressBar.BeginInvoke(new EventHandler((sender, e) => { progressBar.Value = i; }), null); } }
二 線程池
public static bool QueueUserWorkItem(WaitCallback);
public static bool QueueUserWorkItem(WaitCallback, object);
線程池默認為後臺線程(IsBackground)
private void btn3_Click(object sender, EventArgs e) { ThreadPool.QueueUserWorkItem(DoWork2, 100); // 或者 ThreadPool.QueueUserWorkItem((s) => { int minWorkerThreads, minCompletionPortThreads, maxWorkerThreads, maxCompletionPortThreads; ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads); ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads); MessageBox.Show(String.Format("WorkerThreads = {0} ~ {1}, CompletionPortThreads = {2} ~ {3}", minWorkerThreads, maxWorkerThreads, minCompletionPortThreads, maxCompletionPortThreads)); DoWork2(100); }); } // 線程方法 private void DoWork2(object obj) { for (int i = 0; i < (int)obj; i++) { // Thread.Sleep(50); progressBar.BeginInvoke(new EventHandler((sender, e) => { progressBar.Value = i; }), null); } }線程池
三 BackgroundWorker
private void btn4_Click(object sender, EventArgs e) { progressBar.Value = 0; BackgroundWorker bw = new BackgroundWorker(); bw.WorkerReportsProgress = true;// 是否報告進度更新 // 線程執行 bw.DoWork += new DoWorkEventHandler((obj, args) => { for (int i = 0; i < 100; i++) { bw.ReportProgress(i); } }); // UI主線程顯示進度 bw.ProgressChanged += (obj, progressChangedEventArgs) => { progressBar.Value = progressChangedEventArgs.ProgressPercentage; }; // 線程執行完成後的回調函數 bw.RunWorkerCompleted += (obj, runWorkerCompletedEventArgs) => { MessageBox.Show("子線程執行完成!"); }; if (!bw.IsBusy) { bw.RunWorkerAsync(); } }BackgroundWorker
三 Task(.NET 4.0以上版本)
參考博客 http://www.cnblogs.com/luxiaoxun/p/3280146.html
private void btn5_Click(object sender, EventArgs e) { progressBar.Value = 0; Task<bool> t = new Task<bool>(maxValue => DoWork((int)maxValue), progressBar.Maximum); t.Start(); t.Wait(); // 任務完成後繼續延續任務 Task cwt = t.ContinueWith(task => MessageBox.Show("The result is " + t.Result)); } // 線程方法 private bool DoWork(int maxValue) { for (int n = 0; n < maxValue; n++) { progressBar.BeginInvoke(new EventHandler((sender, e) => { progressBar.Value = n; }), null); } return true; }Task
四 異步委托
參考博客 http://www.cnblogs.com/luxiaoxun/p/3280146.html
public delegate string MyDelegate(object arg); private void btn6_Click(object sender, EventArgs e) { MyDelegate myDelegate = new MyDelegate(DoWork3); IAsyncResult result = myDelegate.BeginInvoke(100, DoWork2Callback, "回調函數參數"); // 異步執行完成 string resultStr = myDelegate.EndInvoke(result); } // 線程函數 private string DoWork3(object arg) { for (int n = 0; n < (int)arg; n++) { progressBar.BeginInvoke(new EventHandler((sender, e) => { progressBar.Value = n; }), null); } return "Finished"; } // 異步回調函數 private void DoWork2Callback(IAsyncResult arg) { MessageBox.Show(arg.AsyncState.ToString()); }異步委托
五 附 跨線程訪問UI之 SynchronizationContext (同步上下文)
private void btn2_Click(object sender, EventArgs e) { SynchronizationContext context = SynchronizationContext.Current; new Thread(() => { for (int i = 0; i < 100; i++) { // Send方法是發送一個異步請求消息 //context.Send((s) => //{ // progressBar.Value = i; //}, null); // Post方法是發送一個同步請求消息 context.Post((s) => { progressBar.Value = i; }, null); } }).Start(); }SynchronizationContext
六 參考資料:
☆多線程講解 http://www.w3cschool.cc/csharp/csharp-multithreading.html
☆http://www.cnblogs.com/luxiaoxun/p/3280146.html
[C#] 多線程總結(結合進度條)