如何通过多线程绘制到TBitmap中

时间:2014-06-17 22:23:06

标签: multithreading delphi

为了加速在Delphi XE2中绘制位图,我决定采用以下方式

a)创建一个例如。 10 x线程并在线程类中仅绘制一个位图图层 b)一旦所有线程完成,使用bitblt函数逐层合并位图

我做了以下经验代码

unit Unit_BitmapThread;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Data.DB, Data.Win.ADODB,  ActiveX;



type PaintBitmapThread = class(TThread)

    private

    FBitmap  : TBitmap;
    FConnection : TAdoConnection;
    fserver, fdatabasename, ftablename, fsqlstr : String;
    protected
     procedure Execute; override;
    public
    constructor Create ( bmp_width, bmp_height : Integer; server, databasename, tablename, sqlstr : String; ThreadId : Integer );
    destructor destroy ; override;

end;



type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    FAdoConnection : TAdoConnection;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var    i  : Integer;
    aPaintBitmapThread : PaintBitmapThread;
begin
    for i := 1 to 10 do
         begin
          aPaintBitmapThread :=PaintBitmapThread.Create(100,100,'server','database','table','select *',1);
         end;
end;

{ PaintBitmapThread }

constructor PaintBitmapThread.Create(bmp_width, bmp_height: Integer;
  server, databasename, tablename, sqlstr: String; ThreadId: Integer);
begin
    FBitmap  :=TBitmap.create;
    FConnection :=TAdoConnection.Create(nil);
end;

destructor PaintBitmapThread.destroy;
begin
   FBitmap.Free;
   FConnection.Free;
  inherited;
end;

procedure PaintBitmapThread.Execute;
 var
   ThreadQuery : TADOQuery;
   k : integer;
 begin
   inherited;

   CoInitialize(nil) ; //CoInitialize was not called

   ThreadQuery := TADOQuery.Create(nil) ;
   try
// ADO DB THREAD MUST USE OWN CONNECTION
     ThreadQuery.Connection := FConnection;
//     ThreadQuery.ConnectionString := '????';
//     ThreadQuery.CursorLocation := clUseServer;
//     ThreadQuery.LockType := ltReadOnly;
//     ThreadQuery.CursorType := ctOpenForwardOnly;
     ThreadQuery.SQL.Text := FSQLStr;

//     ThreadQuery.Open;
     while NOT ThreadQuery.Eof and NOT Terminated do
     begin



       //Canvas Does NOT Allow Drawing if not called through Synchronize
       //Synchronize(RefreshCount) ;

       ThreadQuery.Next;
     end;
   finally
     ThreadQuery.Free;
   end;

   CoUninitialize()
end;
end. 

问:a)一旦完成所有10个涂装线程,如何检测 b)如何访问线程[i]并将位图获取到主程序(VCL)进行合并?

最佳解决方案是

if Thread[1] and Thread[2] finished -> newBMP :=  Bitblt( bmp1, bm2);

if also Thread[3]finished -> newBMP :=  Bitblt( newBMP, bm3);
 unit all threads-Bitmaps  are merged

1 个答案:

答案 0 :(得分:4)

  

a)一旦完成所有10个绘制线程,如何检测b)如何访问线程[i]并将位图获取到主程序(VCL)进行合并?

为每个线程添加OnTerminate事件处理程序。这将在主线程上执行。合并此事件处理程序中的位图。因为它在主线程上执行,所以同步得以处理。

如果事件处理程序是线程类的方法,那么它可以访问线程的私有位图对象。

或者,如果您不想使用事件处理程序,请覆盖DoTerminate并从那里同步合并方法。