以下是引用iswith在2022-11-20 12:17:32的发言:
你不要质疑这个,他是多线的!内联C很早就有,我也有这个源码,但大家目标是不一样的
我没质疑什么吧,只是想测试一下消息性能。
只要是用符合系统线程管理和调度的线程都是多线程吧。
VFP的多线程多年前就测试过,当时玩不出什么兴趣就没继续玩。
核心代码可以贴出(注意,只是测试代码,还没完成,只有简单调用COM方法,属性事件的就还没搞)
VFP测试界面,有定时器记录和3个线程记录
MASM32编写的 ComThread.dll 三个相关文件:

程序代码:
;========================
;ComThread.def
;========================
LIBRARY ComThread.dll
EXPORTS
_ProcThread
;========================
;ComThread.inc
;========================
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
include ole32.inc
includelib ole32.lib
include oleaut32.inc
includelib oleaut32.lib
include debug.inc
includelib debug.lib
include shlwapi.inc
includelib shlwapi.lib
DISPPARAMS struct
rgvarg dd ?
rgdispidNamedArgs dd ?
cArgs dd ?
cNamedArgs dd ?
DISPPARAMS ends
VARIANT struct
vt word VT_EMPTY
wReserved1 word 0
wReserved2 word 0
wReserved3 word 0
Union
lVal sdword ?
bVal word ?
iVal sword ?
fltVal real4 ?
dblVal real8 ?
boolVal word ?
scode dword ?
cyVal qword ?
date qword ?
bstrVal dword ?
punkVal dword ?
pdispVal dword ?
parray dword ?
pbVal dword ?
piVal dword ?
plVal dword ?
pfltVal dword ?
pdblVal dword ?
pboolVal dword ?
pscode dword ?
pcyVal dword ?
pdate dword ?
pbstrVal dword ?
ppunkVal dword ?
ppdispVal dword ?
pparray dword ?
pvarVal dword ?
byref dword ?
cVal sbyte ?
uiVal word ?
ulVal dword ?
intVal sword ?
uintVal word ?
pdecVal dword ?
pcVal dword ?
puiVal dword ?
pulVal dword ?
pintVal dword ?
puintVal dword ?
ends
VARIANT ends
OBJPARAMS struct
lpObjName dd ?
lpFunName dd ?
lpParams dd ?
OBJPARAMS ends
.const
IID_IDispatch GUID {00020400h,0000h,0000h,{0C0h,000h,000h,000h,000h,000h,000h,046h}} ;定义IID_IDispatch
.data
stObjParams OBJPARAMS <>
.data?
szDefPath db MAX_PATH dup (?)
;========================
;ComThread.asm
;========================
.386
.model flat,stdcall
option casemap:none
include ComThread.inc
.code
DllEntry proc _dhInstance, _ddReason, _ddReserved
mov eax, TRUE
ret
DllEntry Endp
; 调用对象的函数
; lpIDispatch . COM对象指针
; ddFunOffset . 函数在函数表的偏移,例如要调用第1个函数,偏移是0*4;第2个函数,偏移是1*4
; ddParams .... 参数个数
; lpParams .... 参数表指针
_ComInvoke proc c uses ecx edx _lpIDispatch, _ddFunOffset, _ddParams, _lpParams:vararg
;参数入栈
mov ecx, _ddParams
.while ecx >= 1
dec ecx
mov eax, dword ptr [_lpParams + ecx*4]
push eax
.endw
;调用函数
mov eax, _lpIDispatch
mov edx, [eax]
push _lpIDispatch
mov eax, _ddFunOffset
call dword ptr [edx + eax]
ret
_ComInvoke endp
; IDispatch函数调用,传入函数名和参数列表即可以调用,详情可以参考例子。
; lpIDispatch . COM对象指针
; lpFuncName .. 函数名
; lpVar ....... VARIANT结构指针
; numArgs .....
;_Invoke, lpIDispatch, lpFunName, addr stVar, 1, VT_BSTR, lpParam
_Invoke proc c uses esi edi ebx lpIDispatch, lpFuncName, lpVar, numArgs, args:VARARG ;vartype1,value1,vartype2,value2
LOCAL hMem:DWORD, tmpMem[128]:BYTE, dispid:DWORD, pointer:DWORD
LOCAL stDP:DISPPARAMS
LOCAL IDI_IID_NULL:GUID
invoke RtlZeroMemory, addr IDI_IID_NULL, sizeof GUID
invoke MultiByteToWideChar, CP_ACP, 0, lpFuncName, -1, addr tmpMem, 128
lea eax, tmpMem
mov pointer, eax
; lpIDispatch.GetIDsOfNames()
; [restricted] Void GetIDsOfNames (
; [in] riid :Ptr GUID,
; [in] rgszNames :Ptr Ptr I1,
; [in] cNames :UInt,
; [in] lcid :UI4,
; [out] rgdispid :Ptr I4 )
invoke _ComInvoke, lpIDispatch, 20, 5, addr IDI_IID_NULL, addr pointer, 1, 0, addr dispid
; (numArgs + 1) * sizeof VARIANT
mov eax, numArgs
inc eax
imul eax, sizeof VARIANT
; 从堆中分配空间。GPTR...分配固定的内存并初始化为0,返回一个指针
invoke GlobalAlloc, GPTR, eax
mov hMem, eax
;init params
invoke RtlZeroMemory, addr stDP, sizeof DISPPARAMS
.if numArgs > 0
mov eax, sizeof VARIANT
imul eax, numArgs
mov esi, hMem
lea edi, args
mov eax, numArgs
shl eax, 3 ;numArgs*4*2
sub eax, 8
add edi, eax
assume esi:ptr VARIANT
mov ebx, 0
.while ebx < numArgs
mov eax, [edi]
mov [esi].vt, ax
mov eax, [edi][4]
mov [esi].lVal, eax
mov eax, numArgs
mov stDP.cArgs, eax
mov eax, hMem
mov stDP.rgvarg,eax
add esi,sizeof VARIANT
sub edi,8
inc ebx
.endw
assume esi:nothing
.else
mov stDP.rgvarg, 0
mov stDP.cArgs, 0
.endif
; lpIDispatch.Invoke()
; [restricted] Void Invoke (
; [in] dispidMember :I4,
; [in] riid :Ptr GUID,
; [in] lcid :UI4,
; [in] wFlags :UI2,
; [in] pdispparams :Ptr DISPPARAMS,
; [out] pvarResult :Ptr Variant,
; [out] pexcepinfo :Ptr EXCEPINFO,
; [out] puArgErr :Ptr UInt )
invoke _ComInvoke, lpIDispatch, 24, 8, dispid, addr IDI_IID_NULL, 0, 1, addr stDP, lpVar, 0, 0
invoke GlobalFree, hMem
ret
_Invoke endp
_ProcThread proc uses esi lpParam
LOCAL szBuf[MAX_PATH] :BYTE
LOCAL szGUID :GUID
LOCAL lpIDispatch :DWORD
LOCAL stVar :VARIANT
LOCAL lpPar :DWORD
mov esi, lpParam
assume esi:ptr OBJPARAMS
invoke CoInitialize, NULL
;创建对象
invoke MultiByteToWideChar, CP_ACP, 0, [esi].lpObjName, -1, addr szBuf, MAX_PATH
invoke CLSIDFromProgID, addr szBuf, addr szGUID
.if eax != S_OK
invoke MessageBox, 0, CTEXT("找不到对象"), 0, 0
.endif
invoke CoCreateInstance, addr szGUID, NULL, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, offset IID_IDispatch, addr lpIDispatch
.if eax != S_OK
invoke MessageBox, 0, CTEXT("无法创建对象"), 0, 0
.endif
;调用对象函数
invoke MultiByteToWideChar, CP_ACP, 0, [esi].lpParams, -1, addr szBuf, MAX_PATH
invoke SysAllocString, addr szBuf
mov lpPar, eax
invoke _Invoke, lpIDispatch, [esi].lpFunName, addr stVar, 1, VT_BSTR, lpPar
invoke SysFreeString, lpPar
assume esi:nothing
;释放对象
; lpIDispatch.Release()
; [restricted] UI4 Release ( )
invoke _ComInvoke, lpIDispatch, 2*4, 0
invoke CoUninitialize
ret
_ProcThread endp
End DllEntry