Pool Manager: 一个自动服务程序(Automation Server)示例

一个自动服务程序说明属性和方法程序如何在其他具有自动特性的应用程序中进行设置和调用。

要创建一个自动服务程序,您需要做到:

  1. 创建一个项目。

  2. 向项目中添加一个带有 OLE Public 类的 .vcx 文件,或者添加一个 .prg 文件,在 .prg 文件中定义一个带有 OLEPUBLIC 关键字的类。

  3. 创建一个 .dll 或者一个 .exe 文件。

可以在本地或远程调用一个自动服务程序,通过方法程序的调用或者设置属性来实现商务功能。

这是一个 Pool Manager 示例,它在一个自定义的 OLE Server 中实现。一个客户端可以向 Pool Manager 发送作业(Pool Manager 可以位于一个远程计算机上),并让 Pool Manager 处理作业的执行过程。由于 Pool Manager 的资源处理作业的执行,所以您可以继续执行自己的工作。本示例的作业都是虚设的模拟作业。

若要打开 Pool Manager 示例的项目

若要运行 Pool Manager 示例

  1. 打开 Pool.prj 文件,选择“连编”。

  2. 在“连编选项”对话框中,选择“连编可执行文件”并再选“确定”,这样就可以创建 Pool.exe。当连编该可执行文件时,将注册这个服务程序。

  3. 运行 Pool.scx。

Pool Init 事件

当运行 Pool 表单时,首先要执行的代码是 Init 事件,此事件创建一个 poolmgr 对象:

* Pool Init
SET PROC TO jobmgr.prg
THIS.oPoolMgr = CreateObject('Pool.Poolmgr')

当创建 oPoolMgr 对象时,会定义一个数组来跟踪作业,同时创建一个计时器对象。这个计时器对象基于 PoolTimer 类的基础上,用来检查新作业和已完成的作业。

Pool AddJob 方法程序

当用户在 pool 表单上选择“Print”、“Fax”或者“Excel Chart”按钮时,会调用 AddJob 方法程序。AddJob 执行如下的操作:

  1. 重新定义一个数组,对特别的作业进行跟踪。

  2. 在 NewJob 的一个指定的子类基础上创建一个对象:FaxJob、PrintJob 或者 GraphJob。这些类在 JOBMGR.prg 文件中定义,并作为一个参数被表单引用。

  3. 将这个作业对象传递给 PoolMgr 对象的 NewJob 方法程序:
    PARAMETER cJobType
    LOCAL oNewJobRef
    IF ALEN(THIS.aJobs)>1 OR TYPE('THIS.aJobs[1]') = 'O'
    DIMENSION THIS.aJobs[ALEN(THIS.aJobs)+1]
    ENDIF
    oNewJobRef = CreateObject(m.cJobType,THIS)
    THIS.oPoolMgr.NewJob(m.oNewJobRef)
    

PoolMgr NewJob 方法程序

PoolMgr 对象的 NewJob 方法程序重新定义两个 PoolMgr 作业数组,并将对作业对象的参数存储在新行的第一个元素里,将 0 存储在第二个元素里,表明这是一个新的作业。

PARAMETER oNewJob
IF TYPE('oNewJob') # 'O' OR ISNULL(m.oNewJob)
   RETURN .F.
ENDIF
IF ALEN(THIS.aJobObjs,1) > 1 ;
  OR ISNULL(THIS.aJobObjs[1])
   DIMENSION THIS.aJobObjs[ALEN(THIS.aJobObjs,1)+1,2]
ENDIF
THIS.aJobObjs[ALEN(THIS.aJobObjs,1),1] = oNewJob
THIS.aJobObjs[ALEN(THIS.aJobObjs,1),2] = 0

PoolTimer Timer 事件

每隔三秒钟,会执行 PoolTimer 的 timer 事件代码。此代码在这个作业数组中进行循环。如果第二个参数是 0,表明这是一个新的作业,然后创建一个新的PrintJob, FaxJob 或 GraphJob 对象(poolmgr.prg 文件中 Job 的一个子类)来管理作业。例如,下面的代码行在 PrintJob 的基础上创建一个对象,并将对它的引用存储在 timer 的 aJobs 数组中:

THIS.aJobs[ALEN(THIS.aJobs)] = CREATEOBJECT('Pool.PrintJob')

然后,将此数组中针对该行的第二个元素设置为 1,表明已经开始了该作业,再调用这个新对象的 SetupJob 方法程序。对此作业对象的参数会传递给 SetupJob 方法程序:

THIS.aJobs[ALEN(THIS.aJobs)].SetupJob(THIS.Parent.aJobObjs[m.i,1])

Job 类

在 Poolmgr.prg 文件中定义 Job 类:

DEFINE CLASS Job AS FORM

当在 Job 类或其他任意的 Job 子类基础上创建对象时,该对象的 StartJob 方法程序被调用:

PROCEDURE SetupJob
   PARAMETER oJob
   THIS.oJob = m.oJob
   THIS.Caption = THIS.oJob.Jobtype
   THIS.Visible = .T.
ENDPROC

例如,PrintJob 类是 Job 类的一个子类。如果该对象是在 PrintJob 基础上创建,StartJob 方法程序会执行父类 StartJob 方法程序的默认过程,将设置表单的标题,并显示一个标签。然后,调用 INKEY( ) 函数将时间暂停设置为 10 秒。在本示例的功能实现时,没有使用 INKEY( ) 函数,而在此处通过编写代码来处理打印作业。

DEFINE CLASS PrintJob AS Job OLEPublic
   PROCEDURE StartJob
      DoDefault()
      =INKEY(10)
      THIS.EndJob()
   ENDPROC
ENDDEFINE

该对象的 EndJob 方法程序调用了原来作业对象的 JobDone 方法程序,并释放了 PrintJob、FaxJob 或者 GraphJob 对象。

PROCEDURE EndJob
   THIS.lbl1.caption = 'Ending job...'
   THIS.oJob.JobDone()
   THIS.oJob = .null.
   THIS.Visible = .F.
   THISFORM.Release 
ENDPROC

在原始作业对象的 JobDone 方法程序中的代码,通过调用表单的 JobDone 方法程序,提示表单作业已经完成。

PROCEDURE jobdone
   IF TYPE('THIS.oFormRef')='O'
      THIS.oFormRef.JobDone(THIS.JobType)
   ENDIF
ENDPROC

最后,表单的 JobDone 方法程序在表单上的列表框中显示作业的状态:

PARAMETER cJob
THIS.lstJobs.AddItem(m.cJob+' job is complete.')

Job 对象的生存期

Job 对象(基于在 JOBMGR.prg 文件中定义的 PrintJob、FaxJob 或者 GraphJob 类):