C#線程處理演示代碼
本示例演示了下面的線程處理技術。
創建、啟動和終止線程
使用線程池
線程同步和互交 ThreadPool.cs
using System;
using System.Threading;
// Fibonacci 類為使用輔助
// 線程執行長時間的 Fibonacci(N) 計算提供了一個接口。
// N 是為 Fibonacci 構造函數提供的,此外還提供了
// 操作完成時對象發出的事件信號。
// 然后,可以使用 FibOfN 屬性來檢索結果。
public class Fibonacci
{
public Fibonacci(int n, ManualResetEvent doneEvent)
{
_n = n;
_doneEvent = doneEvent;
}
// 供線程池使用的包裝方法。
public void ThreadPoolCallback(Object threadContext)
{
int threadIndex = (int)threadContext;
Console.WriteLine("thread {0} started...", threadIndex);
_fibOfN = Calculate(_n);
Console.WriteLine("thread {0} result calculated...", threadIndex);
_doneEvent.Set();
}
// 計算第 N 個斐波納契數的遞歸方法。
public int Calculate(int n)
{
if (n <= 1)
{
return n;
}
else
{
return Calculate(n - 1) + Calculate(n - 2);
}
}
public int N { get { return _n; } }
private int _n;
public int FibOfN { get { return _fibOfN; } }
private int _fibOfN;
ManualResetEvent _doneEvent;
}
public class ThreadPoolExample
{
static void Main()
{
const int FibonacciCalculations = 10;
// 每個 Fibonacci 對象使用一個事件
ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations];
Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations];
Random r = new Random();
// 使用 ThreadPool 配置和啟動線程:
Console.WriteLine("launching {0} tasks...", FibonacciCalculations);
for (int i = 0; i < FibonacciCalculations; i++)
{
doneEvents[i] = new ManualResetEvent(false);
Fibonacci f = new Fibonacci(r.Next(20,40), doneEvents[i]);
fibArray[i] = f;
ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i);
}
// 等待池中的所有線程執行計算...
WaitHandle.WaitAll(doneEvents);
Console.WriteLine("Calculations complete.");
// 顯示結果...
for (int i= 0; i<FibonacciCalculations; i++)
{
Fibonacci f = fibArray[i];
Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN);
}
}
}
ThreadStartStop.cs
using System;
using System.Threading;
public class Worker
{
// 啟動線程時調用此方法。
public void DoWork()
{
while (!_shouldStop)
{
Console.WriteLine("worker thread: working...");
}
Console.WriteLine("worker thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Volatile 用于向編譯器提示此數據
// 成員將由多個線程訪問。
private volatile bool _shouldStop;
}
public class WorkerThreadExample
{
static void Main()
{
// 創建線程對象。這不會啟動該線程。
Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);
// 啟動輔助線程。
workerThread.Start();
Console.WriteLine("main thread: Starting worker thread...");
// 循環直至輔助線程激活。
while (!workerThread.IsAlive);
// 為主線程設置 1 毫秒的休眠,
// 以使輔助線程完成某項工作。
Thread.Sleep(1);
// 請求輔助線程自行停止:
workerObject.RequestStop();
// 使用 Join 方法阻塞當前線程,
// 直至對象的線程終止。
workerThread.Join();
Console.WriteLine("main thread: Worker thread has terminated.");
}
}
ThreadSync.cs
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
// 將線程同步事件封裝在此類中,
// 以便于將這些事件傳遞給 Consumer 和
// Producer 類。
public class SyncEvents
{
public SyncEvents()
{
// AutoResetEvent 用于“新項”事件,因為
// 我們希望每當使用者線程響應此事件時,
// 此事件就會自動重置。
_newItemEvent = new AutoResetEvent(false);
// ManualResetEvent 用于“退出”事件,因為
// 我們希望發出此事件的信號時有多個線程響應。
// 如果使用 AutoResetEvent,事件
// 對象將在單個線程作出響應之后恢復為
// 未發信號的狀態,而其他線程將
// 無法終止。
_exitThreadEvent = new ManualResetEvent(false);
// 這兩個事件也放在一個 WaitHandle 數組中,以便
// 使用者線程可以使用 WaitAny 方法
// 阻塞這兩個事件。
_eventArray = new WaitHandle[2];
_eventArray[0] = _newItemEvent;
_eventArray[1] = _exitThreadEvent;
}
// 公共屬性允許對事件進行安全訪問。
public EventWaitHandle ExitThreadEvent
{
get { return _exitThreadEvent; }
}
public EventWaitHandle NewItemEvent
{
get { return _newItemEvent; }
}
public WaitHandle[] EventArray
{
get { return _eventArray; }
}
private EventWaitHandle _newItemEvent;
private EventWaitHandle _exitThreadEvent;
private WaitHandle[] _eventArray;
}
// Producer 類(使用一個輔助線程)
// 將項異步添加到隊列中,共添加 20 個項。
public class Producer
{
public Producer(Queue<int> q, SyncEvents e)
{
_queue = q;
_syncEvents = e;
}
public void ThreadRun()
{
int count = 0;
Random r = new Random();
while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))
{
lock (((ICollection)_queue).SyncRoot)
{
while (_queue.Count < 20)
{
_queue.Enqueue(r.Next(0, 100));
_syncEvents.NewItemEvent.Set();
count++;
}
}
}
Console.WriteLine("Producer thread: produced {0} items", count);
}
private Queue<int> _queue;
private SyncEvents _syncEvents;
}
// Consumer 類通過自己的輔助線程使用隊列
// 中的項。Producer 類使用 NewItemEvent
// 將新項通知 Consumer 類。
public class Consumer
{
public Consumer(Queue<int> q, SyncEvents e)
{
_queue = q;
_syncEvents = e;
}
public void ThreadRun()
{
int count = 0;
while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
{
lock (((ICollection)_queue).SyncRoot)
{
int item = _queue.Dequeue();
}
count++;
}
Console.WriteLine("Consumer Thread: consumed {0} items", count);
}
private Queue<int> _queue;
private SyncEvents _syncEvents;
}
public class ThreadSyncSample
{
private static void ShowQueueContents(Queue<int> q)
{
// 對集合進行枚舉本來就不是線程安全的,
// 因此在整個枚舉過程中鎖定集合以防止
// 使用者和制造者線程修改內容
// 是絕對必要的。(此方法僅由
// 主線程調用。)
lock (((ICollection)q).SyncRoot)
{
foreach (int i in q)
{
Console.Write("{0} ", i);
}
}
Console.WriteLine();
}
static void Main()
{
// 配置結構,該結構包含線程同步
// 所需的事件信息。
SyncEvents syncEvents = new SyncEvents();
// 泛型隊列集合用于存儲要制造和使用的
// 項。此例中使用的是“int”。
Queue<int> queue = new Queue<int>();
// 創建對象,一個用于制造項,一個用于
// 使用項。將隊列和線程同步事件傳遞給
// 這兩個對象。
Console.WriteLine("Configuring worker threads...");
Producer producer = new Producer(queue, syncEvents);
Consumer consumer = new Consumer(queue, syncEvents);
// 為制造者對象和使用者對象創建線程
// 對象。此步驟并不創建或啟動
// 實際線程。
Thread producerThread = new Thread(producer.ThreadRun);
Thread consumerThread = new Thread(consumer.ThreadRun);
// 創建和啟動兩個線程。
Console.WriteLine("Launching producer and consumer threads...");
producerThread.Start();
consumerThread.Start();
// 為制造者線程和使用者線程設置 10 秒的運行時間。
// 使用主線程(執行此方法的線程)
// 每隔 2.5 秒顯示一次隊列內容。
for (int i = 0; i < 4; i++)
{
Thread.Sleep(2500);
ShowQueueContents(queue);
}
// 向使用者線程和制造者線程發出終止信號。
// 這兩個線程都會響應,由于 ExitThreadEvent 是
// 手動重置的事件,因此除非顯式重置,否則將保持“設置”。
Console.WriteLine("Signaling threads to terminate...");
syncEvents.ExitThreadEvent.Set();
// 使用 Join 阻塞主線程,首先阻塞到制造者線程
// 終止,然后阻塞到使用者線程終止。
Console.WriteLine("main thread waiting for threads to finish...");
producerThread.Join();
consumerThread.Join();
}
}
本文由用戶 wen5 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!