2008年6月14日 星期六

ThreadPool 的用法

在多層式架構(N Tier Architecture)下, 中介層(Middle Tier)擔任工作分派(Dispatch)的任務, 接受前端程式的委託, 將各項工作以非同步方式同時執行, 執行後再將結果傳回; 這時我們常會碰到一個問題, 若前端程式的短時間內委託的工作過多, 會造成中介層負擔過重, 可能會使伺服器當機。因此中介層必須設定工作佇列(Task Queue), 讓過多的工作緩一緩, 等待前面委託的工作處理完, 再從佇列中取出執行, 這就是ThreadPool的功能。

以下是一個簡單的console程式範例, 唯一要注意的是執行緒內一定要用try...catch, 讓執行緒能正常結束。

Imports System
Imports System.Threading
Module Module1
' 非同步工作總數
Private mTaskCount As Integer = 3
Sub Main()
Dim mCompletionEvent As New AutoResetEvent(False) '全部工作完成的通知事件
Dim objStopWatch As New Stopwatch ' 馬錶
objStopWatch.Start() ' 啟動馬錶

' 設定集區的最大執行數及IO數
ThreadPool.SetMaxThreads(1, 1)

' 所有工作送入集區
For i As Integer = 1 To mTaskCount
' 設定執行緒參數
Dim objThreadParameters As New ThreadParametersClass
objThreadParameters.mThreadNumber = i
objThreadParameters.mCompletionEvent = mCompletionEvent

' 工作送入集區
ThreadPool.QueueUserWorkItem(New WaitCallback( _
AddressOf MyAsyncOperation), objThreadParameters)
Next
' 等待全部工作完成的事件通知
mCompletionEvent.WaitOne()

' 停止馬錶並顯示耗費時間
objStopWatch.Stop()
MsgBox(objStopWatch.ElapsedMilliseconds)
End Sub


' 執行緒之工作內容
Sub MyAsyncOperation(ByVal mThreadParameters As Object)
' 取得參數
Dim objThreadParameters As ThreadParametersClass = _
CType(mThreadParameters, ThreadParametersClass)
' 擷取錯誤
Try
Console.WriteLine("WorkItem {0} thread: Performing asynchronous operation.", _
objThreadParameters.mThreadNumber)

' 製造錯誤
If objThreadParameters.mThreadNumber = 2 Then
Dim ds As New DataSet
Console.WriteLine(ds.Tables(0).Rows(0).Item(0))
End If
' 停5秒
Thread.Sleep(5000) ' Sleep for 5 seconds to simulate doing work
Catch
Finally
' 待完成工作數減一
If Interlocked.Decrement(mTaskCount) = 0 Then
CType(objThreadParameters.mCompletionEvent, AutoResetEvent).Set()
End If
End Try
End Sub

' 參數定義
Public Class ThreadParametersClass
Public mThreadNumber As Integer

' ' *****不能使用 new, 因為要使用公共變數 *****
Public mCompletionEvent As AutoResetEvent
End Class
End Module