專案架構
- Calculations (Windows Forms 專案):主視窗
frmCalculations,包含輸入框、4 個運算按鈕、結果顯示標籤。
- Calculator (元件類別):封裝多執行緒計算邏輯,透過事件回報進度與結果。
Calculator 元件核心代碼
using System;
using System.Threading;
public class Calculator
{
// 公共欄位:接收 UI 傳入參數
public int varAddTwo;
public int varFact1;
public int varFact2;
public int varLoopValue;
public double varTotalCalculations = 0;
// 事件委派定義
public delegate void FactorialCompleteHandler(double Factorial, double TotalCalculations);
public delegate void AddTwoCompleteHandler(int Result, double TotalCalculations);
public delegate void LoopCompleteHandler(double TotalCalculations, int Counter);
// 事件
public event FactorialCompleteHandler FactorialComplete;
public event FactorialCompleteHandler FactorialMinusOneComplete;
public event AddTwoCompleteHandler AddTwoComplete;
public event LoopCompleteHandler LoopComplete;
// 階乘計算 (varFact1!)
public void Factorial()
{
double result = 1, totalNow = 0;
for (int i = 1; i <= varFact1; i++)
{
result *= i;
varTotalCalculations += 1;
totalNow = varTotalCalculations;
}
FactorialComplete?.Invoke(result, totalNow);
}
// 階乘計算 (varFact2-1)!
public void FactorialMinusOne()
{
double result = 1, totalNow = 0;
for (int i = 1; i <= varFact2 - 1; i++)
{
result *= i;
varTotalCalculations += 1;
totalNow = varTotalCalculations;
}
FactorialMinusOneComplete?.Invoke(result, totalNow);
}
// 簡單加法
public void AddTwo()
{
int result = varAddTwo + 2;
varTotalCalculations += 1;
AddTwoComplete?.Invoke(result, varTotalCalculations);
}
// 巢狀迴圈模擬高負載
public void RunALoop()
{
double totalNow = 0;
for (int x = 1; x <= varLoopValue; x++)
for (int y = 1; y <= 500; y++)
{
varTotalCalculations += 1;
totalNow = varTotalCalculations;
}
LoopComplete?.Invoke(totalNow, varLoopValue);
}
}
UI 端串接與執行緒啟動
public partial class frmCalculations : Form
{
private Calculator calc = new Calculator();
public frmCalculations()
{
InitializeComponent();
// 訂閱事件
calc.FactorialComplete += (r, t) => { lblFactorial1.Text = r.ToString(); lblTotal.Text = t.ToString(); btnFactorial1.Enabled = true; };
calc.FactorialMinusOneComplete += (r, t) => { lblFactorial2.Text = r.ToString(); lblTotal.Text = t.ToString(); btnFactorial2.Enabled = true; };
calc.AddTwoComplete += (r, t) => { lblAddTwo.Text = r.ToString(); lblTotal.Text = t.ToString(); btnAddTwo.Enabled = true; };
calc.LoopComplete += (t, c) => { lblRunLoops.Text = c.ToString(); lblTotal.Text = t.ToString(); btnRunLoops.Enabled = true; };
}
private void btnFactorial1_Click(object sender, EventArgs e)
{
calc.varFact1 = int.Parse(txtValue.Text);
btnFactorial1.Enabled = false;
ThreadPool.QueueUserWorkItem(_ => calc.Factorial()); // 執行緒池啟動
}
// 其他按鈕同理...
}
關鍵設計重點
- 元件不直接操作 UI,透過事件解耦。
- 參數透過公共欄位傳遞(簡單示範),生產環境建議用
ThreadStart 包裝或 Task 傳遞強型別參數。
- 使用
ThreadPool.QueueUserWorkItem 避免手動管理執行緒生命週期。
- 事件呼叫使用
?.Invoke 防止無訂閱者時擲回 NullReferenceException。