| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2687 人关注过本帖, 1 人收藏
标题:NetMTVFP(1.02版)
只看楼主 加入收藏
iswith
Rank: 6Rank: 6
等 级:侠之大者
威 望:5
帖 子:328
专家分:493
注 册:2013-5-14
收藏
得分:0 
没有什么可比性,不用DLL因为那个会改变VFP的习惯            
。。。。。。,你叫他取个结果集回来,一看性能,二看实现简不简单,不要多,就10W行记录
图片附件: 游客没有浏览图片的权限,请 登录注册


[此贴子已经被作者于2022-11-20 16:20编辑过]

2022-11-20 16:12
foxfans
Rank: 5Rank: 5
等 级:贵宾
威 望:15
帖 子:112
专家分:324
注 册:2021-10-23
收藏
得分:0 
在Vfp WinForm表单上点单X按钮压住不动,试试你的多线程还能不能动。,你这个后台获取数据是基础功,不然失去了多线程的意义,点着还能动,就代表你的其它线程逻辑运行时不受主表单影响,各做各的事,不被影响也不影响主窗口,真正的异步回调结果。另外点击的是你的主表单X,或是VFP开发环境的X不是项目管理器的X。

[此贴子已经被作者于2022-11-20 16:48编辑过]

2022-11-20 16:27
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10538
专家分:42927
注 册:2014-5-20
收藏
得分:0 
以下是引用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


2022-11-20 17:27
foxfans
Rank: 5Rank: 5
等 级:贵宾
威 望:15
帖 子:112
专家分:324
注 册:2021-10-23
收藏
得分:0 
主进程线程调度做到不卡,大量业务量的情况时才不会影响整体性能和其它子线程运行过程,如果主调度卡死,其它子线程就成摆设,类似子线程暂停。
图片附件: 游客没有浏览图片的权限,请 登录注册


[此贴子已经被作者于2022-11-21 23:03编辑过]

2022-11-20 18:45
iswith
Rank: 6Rank: 6
等 级:侠之大者
威 望:5
帖 子:328
专家分:493
注 册:2013-5-14
收藏
得分:0 
以下是引用foxfans在2022-11-20 16:27:26的发言:

在Vfp WinForm表单上点单X按钮压住不动,试试你的多线程还能不能动。,你这个后台获取数据是基础功,不然失去了多线程的意义,点着还能动,就代表你的其它线程逻辑运行时不受主表单影响,各做各的事,不被影响也不影响主窗口,真正的异步回调结果。另外点击的是你的主表单X,或是VFP开发环境的X不是项目管理器的X。


在Vfp WinForm表单上点单X按钮压住不动,试试你的多线程还能不能动,说实话你说这话水平还没有那个吹水佬高,那消息机制的问题,跟多线有什么关系。。。。
2022-11-22 15:40
foxfans
Rank: 5Rank: 5
等 级:贵宾
威 望:15
帖 子:112
专家分:324
注 册:2021-10-23
收藏
得分:0 
Vfp主程序展示的界面或控件除了消息还有自绘更新,其它事件等,一旦你主线程一卡死,怎么和多线程没关系,是有很微妙的关系你不懂载前预处理而己。只有先解决自己线程载入问题后,VFP开发的程序+载入运行库才可以像其它语言一样注入其它进程中执行做外挂或其它任务用。别以为传个_vfp 或sys(3095 去docmd处理内容后,IMPLEMENTS就完事,这事只做一半,主表单一卡死你啥都传不回来,只能瞎等,后台任务少还好,极短时间就回过神让人感觉不出卡,任务一多你主程序自己都歇息了还指望他能高频再分配调度,可以用你的net做个简单的线程高频回调看能不能达到上面的效果,上面数值和二维码生成每次变化都是子线程一个计算结果与主进程的交互,其它不废话。如果是做高调度 高并行任务 支持高并发的主表单,那你这多线程要走的路还长,考虑的要更加全面。

[此贴子已经被作者于2022-11-23 07:37编辑过]

2022-11-23 01:17
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10538
专家分:42927
注 册:2014-5-20
收藏
得分:0 
是不是多线程(或有效的多线程),可以简单测试一下:
1、在主程序启动子线程后进入一个死循环,看看子线程的线程过程还能不能正常动作(可以在主程序的死循环里监视线程过程的情况)。
2、在子线程过程里设置一个线程循环过程,线程循环由主程序控制何时跳出结束线程过程。
如果主程序能实时监视子线程过程和控制子线程过程就应该是OK了,注意,控制是“实时”的,每时每刻,想动就动,想停就停。
2022-11-23 07:54
foxfans
Rank: 5Rank: 5
等 级:贵宾
威 望:15
帖 子:112
专家分:324
注 册:2021-10-23
收藏
得分:0 
这些是多线程基本特性
图片附件: 游客没有浏览图片的权限,请 登录注册



[此贴子已经被作者于2022-11-23 19:32编辑过]

2022-11-23 18:54
快速回复:NetMTVFP(1.02版)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.021583 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved