185 lines
No EOL
7 KiB
VB.net
185 lines
No EOL
7 KiB
VB.net
Option Explicit On
|
|
Option Strict Off
|
|
|
|
Imports System.Threading
|
|
Imports System.Collections
|
|
|
|
Public Delegate Sub ThreadErrorHandlerDelegate(ByVal oWorkItem As ThreadPoolWorkItem, ByVal oError As Exception)
|
|
|
|
Public Class ThreadPoolWorkItem
|
|
Public m_bStoreOutput As Boolean = False
|
|
Public m_sName As String = ""
|
|
Public m_pMethod As [Delegate] = Nothing
|
|
Public m_pInput As Object() = Nothing
|
|
Public m_oOutput As Object = Nothing
|
|
Public m_oException As Exception = Nothing
|
|
Public Sub New()
|
|
End Sub
|
|
Public Sub New(ByVal sName As String, ByVal pMethod As [Delegate], ByVal pInput As Object(), ByVal bStoreOutput As Boolean)
|
|
m_sName = sName
|
|
m_pMethod = pMethod
|
|
m_pInput = pInput
|
|
m_bStoreOutput = bStoreOutput
|
|
End Sub
|
|
End Class
|
|
|
|
Public Class XYThreadPool
|
|
Private m_htThreads As Hashtable = New Hashtable(256)
|
|
Private m_nMinThreadCount As Integer = 5
|
|
Private m_nMaxThreadCount As Integer = 10
|
|
Private m_nShutdownPause As Integer = 200
|
|
Private m_nServerPause As Integer = 25
|
|
Private m_bContinue As Boolean = False
|
|
Private m_oException As Exception = Nothing
|
|
Private m_qInput As Queue = New Queue(1024)
|
|
Private m_qOutput As Queue = New Queue(1024)
|
|
Private m_delegateThreadErrorHandler As [Delegate] = New ThreadErrorHandlerDelegate(AddressOf OnThreadError)
|
|
Private Sub ThreadProc()
|
|
While m_bContinue
|
|
Dim obj As Object = Nothing
|
|
Monitor.Enter(Me)
|
|
If m_qInput.Count > 0 Then obj = m_qInput.Dequeue()
|
|
Monitor.Exit(Me)
|
|
If obj Is Nothing Then
|
|
Dim bQuit As Boolean = False
|
|
Monitor.Enter(Me)
|
|
If m_htThreads.Count > m_nMinThreadCount Then
|
|
m_htThreads.Remove(Thread.CurrentThread.Name)
|
|
bQuit = True
|
|
End If
|
|
Monitor.Exit(Me)
|
|
If bQuit Then Return
|
|
Thread.Sleep(10 * m_nServerPause)
|
|
Else
|
|
Dim oWorkItem As ThreadPoolWorkItem = CType(obj, ThreadPoolWorkItem)
|
|
'oWorkItem.m_oOutput = oWorkItem.m_pMethod.DynamicInvoke(oWorkItem.m_pInput)
|
|
Try
|
|
oWorkItem.m_oOutput = oWorkItem.m_pMethod.DynamicInvoke(oWorkItem.m_pInput)
|
|
Catch oBug As Exception
|
|
If Not m_delegateThreadErrorHandler Is Nothing Then
|
|
Try
|
|
Dim pInput As Object() = {oWorkItem, oBug}
|
|
m_delegateThreadErrorHandler.DynamicInvoke(pInput)
|
|
Catch
|
|
End Try
|
|
End If
|
|
End Try
|
|
If oWorkItem.m_bStoreOutput Then
|
|
Monitor.Enter(m_qOutput)
|
|
m_qOutput.Enqueue(oWorkItem)
|
|
Monitor.Exit(m_qOutput)
|
|
End If
|
|
Thread.Sleep(m_nServerPause)
|
|
End If
|
|
End While
|
|
End Sub
|
|
Private Sub OnThreadError(ByVal oWorkItem As ThreadPoolWorkItem, ByVal oError As Exception)
|
|
If oWorkItem Is Nothing Then
|
|
m_oException = oError
|
|
Else
|
|
oWorkItem.m_oException = oError
|
|
End If
|
|
End Sub
|
|
Public Sub SetThreadErrorHandler(ByVal pMethod As ThreadErrorHandlerDelegate)
|
|
Monitor.Enter(Me)
|
|
m_delegateThreadErrorHandler = pMethod
|
|
Monitor.Exit(Me)
|
|
End Sub
|
|
Public Sub SetServerPause(ByVal nMilliseconds As Integer)
|
|
Monitor.Enter(Me)
|
|
If nMilliseconds > 9 And nMilliseconds < 101 Then m_nServerPause = nMilliseconds
|
|
Monitor.Exit(Me)
|
|
End Sub
|
|
Public Sub SetShutdownPause(ByVal nMilliseconds As Integer)
|
|
Monitor.Enter(Me)
|
|
m_nShutdownPause = nMilliseconds
|
|
Monitor.Exit(Me)
|
|
End Sub
|
|
Public Function GetException() As Exception
|
|
Return m_oException
|
|
End Function
|
|
Public Sub InsertWorkItem(ByVal oWorkItem As ThreadPoolWorkItem)
|
|
Try
|
|
Monitor.Enter(Me)
|
|
m_qInput.Enqueue(oWorkItem)
|
|
If m_bContinue AndAlso m_qInput.Count > m_htThreads.Count AndAlso m_htThreads.Count < m_nMaxThreadCount Then
|
|
Dim th As Thread = New Thread(AddressOf ThreadProc)
|
|
th.Name = Guid.NewGuid.ToString()
|
|
m_htThreads.Add(th.Name, th)
|
|
th.Start()
|
|
End If
|
|
Catch oBug As Exception
|
|
m_oException = oBug
|
|
Finally
|
|
Monitor.Exit(Me)
|
|
End Try
|
|
End Sub
|
|
Public Sub InsertWorkItem(ByVal sName As String, ByVal pMethod As [Delegate], ByVal pArgs As Object(), ByVal bStoreOutput As Boolean)
|
|
InsertWorkItem(New ThreadPoolWorkItem(sName, pMethod, pArgs, bStoreOutput))
|
|
End Sub
|
|
Public Function ExtractWorkItem() As ThreadPoolWorkItem
|
|
Dim oWorkItem As Object = Nothing
|
|
Monitor.Enter(m_qOutput)
|
|
If m_qOutput.Count > 0 Then oWorkItem = m_qOutput.Dequeue()
|
|
Monitor.Exit(m_qOutput)
|
|
If oWorkItem Is Nothing Then Return Nothing
|
|
Return CType(oWorkItem, ThreadPoolWorkItem)
|
|
End Function
|
|
Public Function StartThreadPool(Optional ByVal nMinThreadCount As Integer = 5, Optional ByVal nMaxThreadCount As Integer = 10) As Boolean
|
|
Try
|
|
Monitor.Enter(Me)
|
|
If m_bContinue = False Then
|
|
m_bContinue = True
|
|
If nMinThreadCount > 0 Then
|
|
m_nMinThreadCount = nMinThreadCount
|
|
End If
|
|
If nMaxThreadCount > m_nMinThreadCount Then
|
|
m_nMaxThreadCount = nMaxThreadCount
|
|
Else
|
|
m_nMaxThreadCount = 2 * m_nMinThreadCount
|
|
End If
|
|
Dim i As Integer
|
|
For i = 1 To m_nMinThreadCount
|
|
Dim th As Thread = New Thread(AddressOf ThreadProc)
|
|
th.Name = Guid.NewGuid.ToString()
|
|
m_htThreads.Add(th.Name, th)
|
|
th.Start()
|
|
Next i
|
|
End If
|
|
Return True
|
|
Catch oBug As Exception
|
|
m_bContinue = False
|
|
m_oException = oBug
|
|
Return False
|
|
Finally
|
|
Monitor.Exit(Me)
|
|
End Try
|
|
End Function
|
|
Public Sub StopThreadPool()
|
|
Monitor.Enter(Me)
|
|
m_bContinue = False
|
|
Thread.Sleep(Math.Max(200, m_nShutdownPause))
|
|
If (m_nShutdownPause > 0) Then
|
|
Dim dict As IDictionaryEnumerator = m_htThreads.GetEnumerator()
|
|
While dict.MoveNext()
|
|
Dim th As Thread = CType(dict.Value(), Thread)
|
|
If th.IsAlive Then
|
|
Try
|
|
th.Abort()
|
|
Catch
|
|
End Try
|
|
End If
|
|
End While
|
|
End If
|
|
m_htThreads.Clear()
|
|
m_qInput.Clear()
|
|
' m_qOutput.Clear()
|
|
Monitor.Exit(Me)
|
|
End Sub
|
|
Public Function GetThreadCount() As Integer
|
|
Monitor.Enter(Me)
|
|
Dim nCount As Integer = m_htThreads.Count
|
|
Monitor.Exit(Me)
|
|
Return nCount
|
|
End Function
|
|
End Class |