QWorker信号作业处理详解

QWorker的信号作业是一个可以说是很好玩的特色功能,它可以让你做出很好的松散耦合的程序,而松散耦合是软件设计过程中,被人推崇的一种设计模式。

为什么说QWorker的信号作业是松散耦合的呢?因为它具体以下特点:

1、信号的触发者根本就不知道有没有关注这个信号,它的任务就是触发这个信号而已;

2、信号的响应者根本就不知道这个信号是不是会一定触发,它的任务就是万一发生了这个信号,就要做出相应的动作;

3、信号触发者和响应者彼此之间可以完全来自不同的模块,它们之间通过QWorkers完成了相互间的耦合和解除耦合。

下面,我们就了解下信号作业的详细处理过程(下面的代码来自QWorkerDemo):

1、首先,要注册一个信号,注册结果为返回一个信号ID。信号可以重复注册,重复注册会返回同一个信号ID。我们一般用这个ID来做为参数传递给后续的处理过程。

// 注册一个信号触发函数,以便在触发时执行
FSignalId := Workers.RegisterSignal('MySignal.Start');

2、对于信号触发者,它现在唯一需要做的就是调用Workers.Signal来触发信号。触发信号的方式可以按照名称或者信号ID,但我们更推荐信号ID,因为它可以更高效。

//按信号编码触发作业
Workers.Signal(FSignalId);
 
//或者按信号名称触发作业
Workers.Signal('MySignal.Start');

3、对于信号的响应者,它现在需要做的就是调用Workers.Wait函数来注册一个等待信号作业处理函数,这个函数在信号被触发时,会被调用用来处理具体的操作。

Workers.Wait(SignalWaitProc, FSignalId,True);

SingalWaitProc是具体的处理函数,参考代码如下:

procedure TForm1.DoSignalJobMsg(AJob:PQJob);
begin
Label2.Caption := Format('信号MySignal.Start已触发 %d次', [AJob.Runs]);
end;

好了,现在一切就绪,一旦信号被触发,响应者的作业处理函数就会被异步调用了。

【注】

由于我们使用的信号作业处理函数访问了窗体上的元素,而它们不是线程安全的,所以必需在主线程中运行,所以第3步中的Wait我们要求SignalWaitProc在主线程中运行,如果不需要与主线程交互,则作业最后一个参数不传或传为False即可在后台线程中完成作业。

分享到: