close
以下根據 DKTD-WinFormThreading 文章節錄重點
1.
自己建立thread
優點: 精確管理thread生命週期
缺點: 執行緒數目過多時 ,CPU會耗費太多的資源處理Context Switching
2.
利用Threadpool
優點: 會依CPU 數或 CPU 核心數決定適當的 Thread 數處理排入Queue的工作
1: ThreadPool.QueueUserWorkItem(new WaitCallback(Job), parameter);
缺點: 顯示結果需跨執行緒,所以需要使用到以下技能,包含delegate,invoke(同步)/beginInvoke(非同步)。
1:
2:
3:
4: private void Job(object path)
5: {
6: //重設統計數據
7: fileCount = 0;
8: totalSize = 0;
9: //統計檔案數及大小
10: explore(path.ToString());
11:
12: //顯示結果 (跨執行緒)
13: string text = $"{fileCount} files, {totalSize} bytes";
14:
15: //透過Invoke,強制以UI Thread執行
16: this.Invoke(
17: new UpdateLabelHandler(printResult),
18: new object[] { text });
19: }
20: //宣告一個delegate
21: delegate void UpdateLabelHandler(string text);
22: //透過Invoke,printReulst會以UI Thread執行
23: //故可隨意存取UI Control
24: private void printResult(string text)
25: {
26: lblResult.Text = text;
27: }
3.
利用.NET2.0 Backgroundworker
優點:簡單易上手
1: private void runBtn_Click(object sender, EventArgs e)
2: {
3: if(runBtn.Text == "Run")
4: {
5: runBtn.Text = "Cancel";
6: lblResult.Text = string.Empty;
7:
8: fileCount = 0;
9: totalSize = 0;
10: backgroundWorker1.RunWorkerAsync(txtPath.Text);
11: }
12: else
13: {
14: //設定取消旗標
15: backgroundWorker1.CancelAsync();
16: //cancel = true;
17:
18: //在完全停止前,停用按鈕
19: runBtn.Enabled = false;
20:
21: }
22:
23: }
搜尋資料夾工作
1: private void explortFolderJob(string path, BackgroundWorker worker)
2: {
3: //使用遞迴搜索所有目錄
4: foreach (string dir in Directory.GetDirectories(path))
5: {
6: //使用者要求中止
7: if (worker.CancellationPending) return;
8: explortFolderJob(dir, worker);
9: }
10:
11: foreach (string file in Directory.GetFiles(path))
12: {
13: //使用者要求中止
14: if (worker.CancellationPending) return;
15:
16: Interlocked.Increment(ref fileCount);
17:
18: //每100個檔案回報一下進度
19: if(fileCount%100==0)
20: {
21: this.Invoke(
22: new UpdateLabelHandler(updateProgress),
23: $"{fileCount} files"
24: );
25: }
26:
27: //fileCount++;
28: //加總檔案大小
29: FileInfo fi = new FileInfo(file);
30: totalSize += fi.Length;
31: }
32: }
DoWork、ProgressChanged、RunWorkerCompleted
1: private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
2: {
3: explortFolderJob((string)e.Argument, sender as BackgroundWorker);
4: //執行完成,設執行定結果
5: if (backgroundWorker1.CancellationPending)
6: e.Cancel = true;
7: else
8: e.Result = $"{fileCount} files, {totalSize} bytes";
9: }
10:
11: private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
12: {
13: lblResult.Text = e.UserState.ToString();
14: }
15:
16: private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
17: {
18: lblResult.Text = (e.Cancelled) ? "Canceled" : //取消
19: e.Result.ToString(); // 結果
20: runBtn.Text = "Run";
21: runBtn.Enabled = true;
22: }
非同步(Asynchronous)不在於提高效能(Performance),而是增加產能(Throughput)
非同步不等於多執行緒
非同步只對 I/O 相關作業有效,對吃 CPU 的作業沒轍
async 像病毒一樣會傳染
參考資料
------------------------------------------------------------------
4. 執行緒集區與 Execution Context (4)
5. C# 學習筆記:多執行緒 (5) — 工作の取消和逾時
7. 不要寫「假的」非同步方法
------------------------------------------------------------------
全站熱搜