西瓜皮

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
Option Explicit

Private Declare Function CreateWin32Thread Lib "kernel32" Alias "CreateThread" (ByVal lpThreadAttributes As Long, ByVal dwStackSize As Long, ByVal lpStartAddress As Long, ByVal lpParameter As Long, ByVal dwCreationFlags As Long, lpThreadID As Long) As Long
Private Declare Function TerminateThread Lib "kernel32" (ByVal hThread As Long, ByVal dwExitCode As Long) As Long
Private Declare Function SetThreadPriority Lib "kernel32" (ByVal hThread As Long, ByVal nPriority As Long) As Long
Private Declare Function GetThreadPriority Lib "kernel32" (ByVal hThread As Long) As Long
Private Declare Function ResumeThread Lib "kernel32" (ByVal hThread As Long) As Long
Private Declare Function SuspendThread Lib "kernel32" (ByVal hThread As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, Optional ByVal Length As Long = 4)
Private Declare Function WriteProcessMemory Lib "kernel32.dll" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByRef lpBuffer As Any, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32.dll" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function GetModuleHandle Lib "kernel32.dll" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function TlsSetValue Lib "kernel32" (ByVal dwTlsIndex As Long, ByVal lpTlsValue As Long) As Long
Private Declare Function TlsGetValue Lib "kernel32" (ByVal dwTlsIndex As Long) As Long

Enum CreateOperation
  CREATE_SUSPENDED = &H4
  CREATE_ENABLED = 0&
End Enum

Enum ThreadPriority
  THREAD_PRIORITY_LOWEST = -2
  THREAD_PRIORITY_BELOW_NORMAL = -1
  THREAD_PRIORITY_NORMAL = 0
  THREAD_PRIORITY_ABOVE_NORMAL = 1
  THREAD_PRIORITY_HIGHEST = 2
End Enum

Private Type ThisClassSet
  t_ThreadHandle   As Long
  t_ThreadID       As Long
  t_ThreadPriority As Long
  c_ThdEnabled  As Boolean
  m_ThreadTlsData(1 To 64) As Long
End Type
Private PG As ThisClassSet

Private LinkProc() As Long
Event ThreadEntry(ByVal UserParam As Long, ByVal ThreadHandle As Long, ByVal ThreadID As Long)


Private Function ThreadEntryProc(ByVal Param As Long) As Long
  '********************************************************************
  '  None = ThreadEntryProc( 用户自定义参数 )
  '********************************************************************
      
    Dim i As Long
    For i = 1 To 64: TlsSetValue i, PG.m_ThreadTlsData(i): Next
    RaiseEvent ThreadEntry(Param, PG.t_ThreadHandle, PG.t_ThreadID)     '抛出多线程入口事件
    TerminateCurrentThread
'    Call ThreadEntry(Param, PG.t_ThreadHandle, PG.t_ThreadID)
End Function

Function CreateThread(ByVal lParam As Long, Optional cEnabled As CreateOperation = CREATE_ENABLED) As Long
  '********************************************************************
  '  线程句柄 = CreateThread( 用户自定义参数, [线程创建时的操作])
  '********************************************************************
  
  Dim ThreadEntryAddress  As Long
  If PG.t_ThreadID Then Exit Function
  ThreadEntryAddress = GetClassProcAddress(LinkProc, 9, 1)              '获取 ThreadEntryProc 的函数地址
  PG.t_ThreadHandle = CreateWin32Thread(0, 0, ThreadEntryAddress, lParam, cEnabled, PG.t_ThreadID)
  If PG.t_ThreadHandle Then CreateThread = PG.t_ThreadHandle: PG.c_ThdEnabled = CBool(cEnabled)

End Function

Sub TerminateCurrentThread(Optional ByVal ExitCode As Long = 1)
  '********************************************************************
  '  TerminateCurrentThread( [退出码] )
  '********************************************************************

  With PG
    If PG.t_ThreadID Then
        TerminateThread PG.t_ThreadHandle, ByVal ExitCode&
        CloseHandle .t_ThreadHandle
        .t_ThreadID = 0
        .t_ThreadHandle = 0
        .c_ThdEnabled = False
    End If
  End With
End Sub

Property Get ThreadHandle() As Long
  ThreadHandle = PG.t_ThreadHandle
End Property

Property Get ThreadID() As Long
  ThreadID = PG.t_ThreadID
End Property

Property Get Priority() As ThreadPriority
  Priority = GetThreadPriority(PG.t_ThreadPriority)
End Property

Property Let Priority(ByVal tmpValue As ThreadPriority)
  PG.t_ThreadPriority = tmpValue
  Call SetThreadPriority(PG.t_ThreadHandle, tmpValue)
End Property

Property Get Enabled() As Boolean
  Enabled = PG.c_ThdEnabled
End Property

Property Let Enabled(ByVal tmpValue As Boolean)
  PG.c_ThdEnabled = tmpValue
  If tmpValue = True Then
    ResumeThread (PG.t_ThreadHandle)
  ElseIf tmpValue = False Then
    SuspendThread (PG.t_ThreadHandle)
  End If
End Property

Private Sub Class_Initialize()
    '初始化多线程
    ThreadTlsInitial
End Sub

Private Sub Class_Terminate()
    '类销毁时强制销毁线程
   Call TerminateCurrentThread
End Sub

Private Sub ThreadTlsInitial()
    '获取新线程的运行环境数据
    Dim i As Long
    For i = 1 To 64
        PG.m_ThreadTlsData(i) = TlsGetValue(i)
    Next
    WriteProcessMemory -1&, ByVal GetProcAddress(GetModuleHandle("msvbvm60.dll"), "__vbaSetSystemError"), &HC3, 1&, 0&
End Sub

Private Function GetClassProcAddress(LinkProc() As Long, ByVal SinceCount As Long, ByVal ParamsCount As Long) As Long
    '为新线程的回调函数获取函数地址
    Dim mePtr As Long
    Dim jmpAddress As Long
    mePtr = ObjPtr(Me)
    CopyMemory jmpAddress, ByVal mePtr, 4
    CopyMemory jmpAddress, ByVal jmpAddress + (SinceCount - 1) * 4 + &H1C, 4
    ReDim LinkProc(8)
    LinkProc(0) = &H83EC8B55: LinkProc(1) = &HFC8BFFEC: LinkProc(2) = &H3308758D: LinkProc(3) = &HFCFFB1C9
    LinkProc(4) = &HFF68A5F3: LinkProc(5) = &HB8FFFFFF: LinkProc(6) = &HFFFFFFFF: LinkProc(7) = &HC2C9D0FF: LinkProc(8) = &HFF
    CopyMemory ByVal VarPtr(LinkProc(1)) + 1, ParamsCount * 4, 1
    CopyMemory ByVal VarPtr(LinkProc(3)) + 2, ParamsCount, 1
    CopyMemory ByVal VarPtr(LinkProc(4)) + 3, mePtr, 4
    CopyMemory ByVal VarPtr(LinkProc(6)), jmpAddress, 4
    If ParamsCount = 0 Then CopyMemory ByVal (VarPtr(LinkProc(7)) + 3), &HC3, 1
    LinkProc(8) = ParamsCount * 4
    GetClassProcAddress = VarPtr(LinkProc(0))
End Function

实验了好几个类和模块,就这个类相对比较稳定,而且使用也简单。还有个dll多线程也很稳定,不想用dll就不放了。

posted on 2012-11-23 17:00  西瓜皮  阅读(813)  评论(0编辑  收藏  举报