| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 27 人关注过本帖
标题:Multiprocessing with a COM Server
取消只看楼主 加入收藏
詹斯邦
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2022-2-12
收藏
 问题点数:10 回复次数:2 
Multiprocessing with a COM Server
由于正在看文章,所以一些可见的中文化没有完全做,姑且有能力的坛友,自己看哈

So this is for anybody interested in parallel code execution.

And I know I could point out several things already existing, I even did in posts in these threads. I mentioned the existence of ParallelFox: https://
I mentioned the simplest parallel execution possible with RUN /N another.EXE, possibly with parameters.
I mentioned you could run two executables and do IPC - interprocess communication - with windows messages.
我提到过,您可以运行两个可执行文件,并使用windows消息进行IPC(进程间通信)。
I mentioned an approach of Calvin Hsia to allow multithreading and pointed out it has the problem of being data execution, which Windows prevents with data execution prevention - in short DEP.
我提到了Calvin Hsia的一种允许多线程的方法,并指出它存在数据执行的问题,Windows通过数据执行保护——简称DEP——来防止这一点。

And there's more about parallel processing or multithreading with FoxPro out in the internet already, so actually no need to come up with anything new, but I wanted to point out one thing that I think all existing solutions overlooked so far. Making use of an out-of-process COM server as a background process. I'll go into the technical details in one or a few separate posts, this is just the instructions and usage post:
关于FoxPro的并行处理或多线程技术,网上已有大量相关资料,其实无需再赘述。不过我想强调一个现有方案至今都忽略的关键点:
将跨进程COM服务器作为后台进程运行。
具体技术细节我会在后续一两篇独立文章中详细讲解,本文仅提供操作指南和使用说明:
搜索更多相关主题的帖子: COM And the with out 
4 小时前
詹斯邦
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2022-2-12
收藏
得分:0 
So, without going into details of why to do things this way, just the instructions of what to create and how to use it.
1. Build a COM Server "background.process"
1a) Create a new folder "background"
1b) Open VFP this way:
图示为以管理员身份证运行Vfp9
1c) Create a project in the background folder you call "background.pjx" - that way a build of the project will create a background.EXE
1d) Create this as the main.prg of the background.pjx project

CODE
#Define CRLF Chr(13)+Chr(10)

Define Class Process As Form OlePublic
   Hidden ExecuteScriptMessage
   Script = ''
   ExecuteScriptMessage = 0
   Executing = .F.
   ErrorHappened = .F.
   LastReturnValue = .null.
   LastError = ''

   Procedure Init()
      On Shutdown Quit
      * modal states are unwanted, which we can enfore:
      Sys(2335,0) && enable unattended server mode

      Declare Integer RegisterWindowMessage In User32.Dll String cMessage
      Declare Integer PostMessage In User32.Dll Integer nHWnd, Integer nMsg, Integer wParams, Integer lParams

      This.ExecuteScriptMessage = RegisterWindowMessage('BackgroundProcess_ExecuteQueuedTasks')
      If Between(This.ExecuteScriptMessage, 0xC000, 0xFFFF)
         Bindevent(Thisform.HWnd, This.ExecuteScriptMessage , This, 'ExecuteScript', 2+4)
      Else
         Quit
      EndIf      
   Endproc

   Procedure Execute() ;
      HelpString "Execute code in Script property"
      
      Local llDone
      If Not This.Executing && do nothing, if a script still runs
         This.Executing = .T.
         This.ErrorHappened = .F.
         * Postmessage causes ExecuteScript to run, because of the BindEvent in the Init().
         PostMessage(Thisform.HWnd, This.ExecuteScriptMessage, 0, 0)
         llDone = .T.   
      EndIf
            
      Return llDone
   Endproc

   Hidden Procedure ExecuteScript(HWnd As Integer, Msg As Integer, wParam As Integer, Lparam As Integer)
      This.LastReturnValue = Execscript(This.Script)
      This.Executing = .F.

      Return 0
   Endproc

   Procedure Error(nError, cMethod, nLine)
      This.Executing = .F.
      This.ErrorHappened = .T.
      This.LastError = Textmerge("Error <<nError>> in <<cMethod>> Line <<nLine>>: <<Message()>>",.T.)
   Endproc

   Procedure Quit() ;
      HelpString "end the background process"
      Do While Sys(3098,This)>0
         DoEvents
      Enddo
   Endproc

   Procedure Destroy()
      Sys(2335,1) && disable unattended server mode again
      On Shutdown
      Quit
   Endproc
Enddefine

1e) build the EXE

Now you will have a background.process COM server in your system.

2. Using the Background.Process COM server.
This new COM server has the following properties and methods of interest:
4 小时前
詹斯邦
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2022-2-12
收藏
得分:0 
Script - a property you set to a script of VFP code you want to execute in parallel.
Executing - this property tells you whether the background process is executing .script
ErrorHappened - tells you whether an error happened
LastReturnValue - property containing the last value returned from the last successfully ran .script
LastError - the last error from the last unsuccessfully ran .script
Execute() - the method to execute the code in the Script property.
Quit() - quitting the background process

I explain why I chose this structure in a separate thread. A simple example of how to use this is:
CODE
Clear
Public goBackgroundprocess
goBackgroundprocess = Createobject("background.process")
Text To goBackgroundprocess.Script NoShow
Declare Integer Sleep in Win32API Integer milliseconds
Sleep(1000)
Return 42
EndText
goBackgroundprocess.Execute()
? Seconds()
Do while goBackgroundprocess.Executing
   Doevents
EndDo
? Seconds(), goBackgroundprocess.LastReturnValue
goBackgroundprocess.Quit()
Release goBackgroundprocess
It's actually a usage that waits for the result, which you'd normally not do, as you want this to run in parallel to what your application does, but printing the Seconds(), then waiting for goBAcgroundPRocess not executing anymore and printing seconds() with the lastreturnvalue proves, that the call goBackgroundprocess.Execute() returns immediately and the return value of the script (return 42) comes back a second later. So this is true multiprocessing.

In general, the usage is to
I. Set goBackgroundprocess.Script to the code you want to execute in parallel
II. call goBackgroundprocess.Execute()

If the script causes an error within goBackgroundprocess, goBackgroundprocess.ErrorHappened will be set .T. and the error message will be put into goBackgroundprocess.LastError. In this version of it, the line of error will always be the ExecScript line of the ExecuteScript method and not the line number within the script that actually caused the error, that's harder to refine, but maybe in an advanced version I'll provide this.

this concludes the "How To" part of it, just a few last remarks; The scripts you can execute will not see any of the main application process variables, not even public variables. It will not see any workareas of any data session, so the scripts you run have to be able to run completely standalone. There is no mechanism foreseen to pass in parameters, but you can of course generate the script code to set some variables to values as you like or need, or you pass data via DBFs the cript opens and scans or by adding properties to the goBackgroundprocess object.

I intentionally use a public variable goBackgroundprocess for the COM server, as you usally want to have the ability to run parallel code anywhere in your application and to avoid the overhead of creating the object, which can take up to a few seconds in the worst case I measured. This way this initialization becomes only a onetime penalty. What's important for the "How To" usage is, that you quit the background process by calling Quit() and releasing the variable goBackgroundprocess, the background.exe will not disappear from the task manager detail tab, if you only call Quit(). It will only disappear once you do the latter, once you release the variable as the last reference keeping the EXE from quitting.

I will describe technical details about this in a late thread and also some advanced ways of using it, which allow usage of code or classes from your own EXE within the background.process.
4 小时前
快速回复:Multiprocessing with a COM Server
数据加载中...
 
   



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

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018977 second(s), 11 queries.
Copyright©2004-2025, BC-CN.NET, All Rights Reserved