基于 QWorker 的多线程编程-第一个作业

要使用 QWorker 进行后台线程作业,我们要做的第一件事,就是当然就是要引用 QWorker 这个单元,在 C++ Builder 中,要包含 qworker.hpp。

【Delphi】

uses qworker;

【C++ Builder】

#include "qworker.hpp"

在 C++ Builder 中,我们还需要以下两步之一:

(1)、将 qworker 相关的 .pas 加入到当前工程中,这样 C++ Builder 就会自动编译生成 qworker.hpp,并在链接时将 qworker.obj 链接到程序中。

(2)、先建立一个临时的工程,将 qworker 相关的 .pas 加入后编译生成的 *.hpp 复制到 C++ Builder 的Include 目录下,将*.obj 复制到 Lib 目录下,这样以后只需要直接包含 qworker.hpp 就可以了。

做好上面的准备工作后,我们就可以做一个最简单的作业了。好吧,我们的作业只干一件事,显示一个经典的的“Hello,world!”。

首先添加一个主线程作业处理函数 DoHelloworld,这个函数之所以要求运行在主线程,是因为用 ShowMessage 是 VCL 函数,它不是线程安全的,所以要运行在主线程中。然后我们在窗体上添加一个按钮 Button1,然后设置其 OnClick 事件来触发作业处理函数。完成后的代码如下:

【Delphi】

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,qworker, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure DoHelloworld(AJob:PQJob);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
Workers.Post(DoHelloworld,nil,True);
end;

procedure TForm1.DoHelloworld(AJob: PQJob);
begin
ShowMessage('Hello,world');
end;

end.

【C++ Builder】

(1)头文件:Unit1.h

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include "qworker.hpp"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
	TButton *Button1;
	void __fastcall Button1Click(TObject *Sender);
private:	// User declarations
	void __fastcall DoHelloworld(PQJob AJob);
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

(2)主文件:Unit1.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::DoHelloworld(PQJob AJob)
{
ShowMessage("Hello,world");
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Workers->Post(DoHelloworld,NULL,true);
}
//---------------------------------------------------------------------------

看看程序的运行效果:

好了,效果看到了。我们看看刚才用到的 Post 函数的声明:

【Delphi】

function Post(AProc: TQJobProc; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;

【C++ Builder】

NativeInt __fastcall Post(TQJobProc AProc, void * AData, bool ARunInMainThread = false, TQJobDataFreeType AFreeType = (TQJobDataFreeType)(0x0))/* overload */;

这个函数的作业是投寄一个需要立即在后台执行的作业,如果成功,返回一个作业的句柄实例,如果失败,返回0。其参数含义如下:

  • AProc :要执行的作业处理函数
  • AData :作业附加的用户数据指针,其具体含义由作业处理函数自行解析,可以用来传递作业需要的参数
  • ARunInMainThread:作业是否要求在主线程中执行,如果作业需要在主线程执行,则设置为true,如果不需要,则设置为 false

好了,这个最经典的HelloWorld就此搞定,是不是觉得很简单?好复杂?!算了,编程不适合你,开玩笑:)

分享到: