如何通过多线程绘制到TBitmap中 [英] How to paint by multi threading into a TBitmap

查看:121
本文介绍了如何通过多线程绘制到TBitmap中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

加快在Delphi XE2中绘制位图,我决定按照以下方式进行绘图。



a)创建一个例如。 10 x线程和油漆只有线程类
b内的一层位图)一旦所有线程完成,使用bitblt函数逐层合并位图



我做了以下实验代码

  unit Unit_BitmapThread; 

接口

使用
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;覆盖
public
构造函数Create(bmp_width,bmp_height:Integer; server,databasename,tablename,sqlstr:String; ThreadId:Integer);
析构函数破坏;覆盖

end;



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

var
Form1:TForm1;

实现

{$ R * .dfm}

程序TForm1.Button1Click(发件人:TObject);
var i:整数;
aPaintBitmapThread:PaintBitmapThread;
begin
for i:= 1 to 10 do
begin
aPaintBitmapThread:= PaintBitmapThread.Create(100,100,'server','database','table','select * ',1);
结束
结束

{PaintBitmapThread}

构造函数PaintBitmapThread.Create(bmp_width,bmp_height:Integer;
server,databasename,tablename,sqlstr:String; ThreadId:Integer);
begin
FBitmap:= TBitmap.create;
FConnection:= TAdoConnection.Create(nil);
结束

析构函数PaintBitmapThread.destroy;
begin
FBitmap.Free;
FConnection.Free;
继承;
结束

程序PaintBitmapThread.Execute;
var
ThreadQuery:TADOQuery;
k:integer;
开始
继承;

CoInitialize(nil); // CoInitialize没有被调用

ThreadQuery:= TADOQuery.Create(nil);
try
// ADO DB THREAD必须使用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不允许绘图,如果不通过同步调用
// Synchronize(RefreshCount);

ThreadQuery.Next;
结束
finally
ThreadQuery.Free;
结束

CoUninitialize()
end;
结束。

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



最佳解决方案将是

 如果Thread [1]和Thread [2]完成 - > newBMP:= Bitblt(bmp1,bm2); 

如果还有Thread [3]完成 - > newBMP:= Bitblt(newBMP,bm3);
单位所有线程 - 位图被合并


解决方案


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


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



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



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


to speed up painting a bitmap in Delphi XE2, I decided to go the following way

a) Create a eg. 10 x Thread and paint only one layer of the bitmap inside the thread class b) once all threads a finished, merge the bitmaps using the bitblt function layer by layer

I did the following experiemental code

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. 

Q : a) How to detect once all 10 painting threads are finished and b) How to access the thread[i] and get the bitmap to the main program (VCL) for merging ?

Best solution would be

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

解决方案

a) How to detect once all 10 painting threads are finished and b) How to access the thread[i] and get the bitmap to the main program (VCL) for merging?

Add an OnTerminate event handler for each thread. This will execute on the main thread. Merge the bitmaps in this event handler. Because it executes on the main thread, synchronization is taken care of.

If the event handler is a method of the thread class then it can gain access to the thread's private bitmap object.

Alternatively, if you don't want to use the event handler, override DoTerminate and synchronize the merge method from there.

这篇关于如何通过多线程绘制到TBitmap中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆