我想加快绘制位图,因此我设计了一个像BITMAP THREAD CLASS这样的类。完成部分图像的单独绘制后,我想合并Thread.done过程中的所有图像 我的代码就像这样
type
TbmpthreadForm = class(TForm)
.....
THreadImage: TImage;
procedure Button_threadstartClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private-Deklarationen }
procedure ThreadDone(Sender: TObject);
public
{ Public-Deklarationen }
fserver, fdatabasename, ftablename: String;
global_thread_counter: Integer;
XPixel, YPixel: Integer;
Masterbitmap: TBitmap;
end;
var
bmpthreadForm: TbmpthreadForm;
implementation
{$R *.dfm}
procedure TbmpthreadForm.ThreadDone(Sender: TObject);
begin
dec(global_thread_counter);
MyStatusBar.SimpleText := 'Thread Count ->' + IntToStr(global_thread_counter);
Masterbitmap.Canvas.Lock;
with (Sender as TPaintBitmapThread) do
begin
bitblt(Masterbitmap.Canvas.handle, 0, 0, XPixel, YPixel,
bitmap.Canvas.handle, 0, 0, srcand);
THreadImage.Picture.Bitmap.Assign(Masterbitmap);
// lets see local tthread intermediate results and save it to HD
THreadImage.Picture.Bitmap.SaveToFile('c:\temp\myimage' + IntToStr(Index)
+ '.bmp');
end;
Masterbitmap.Canvas.UnLock;
if (global_thread_counter = 0) then
begin
...
end;
end;
procedure TbmpthreadForm.Button_threadstartClick(Sender: TObject);
var
.....
begin
index_max := 2000000;
threadCounter := 10;
Indexdelta := round(index_max / threadCounter);
///
///
....
Masterbitmap.Width := XPixel;
Masterbitmap.Height := YPixel;
for i := 0 to threadCounter - 1 do
begin
n := i * Indexdelta;
m := (i + 1) * Indexdelta;
// just a test sql string ....
sqlstr := 'select * from Mytable where objectindex <' + IntToStr(m) +
' and Objectindex >' + IntToStr(n);
aPaintBitmapThread := TPaintBitmapThread.Create(XPixel, YPixel, ...... , fserver, fdatabasename, ftablename,
sqlstr, i);
aPaintBitmapThread.OnTerminate := ThreadDone;
Memo1.Lines.Add('start thread->' + IntToStr(i));
inc(global_thread_counter);
end;
end;
Thread.done设计遵循SO上的上一个主题(reference question 由于生成的图像/ Masterbitmap看起来与运行运行有点不同,我想我的方法不是线程安全设计,用于复制Thread bmp内容到VCL mainform中的masterbitmap, 我在代码中看不到任何错误,有什么问题????
其他问题
Q1:TPaintBitmapThread里面的fbitmap是在Thread.create程序里面创建的,对于TAdoconnection我找到了注释,它应该在thread.execute里面创建。这也必须在位图上完成吗?
Q2:附加图像显示了线程的图像(位图)的预期结果和实际图像结果(由 THreadImage.Picture.Bitmap.SaveToFile命令看到)
答案 0 :(得分:1)
bitblt(Masterbitmap.Canvas.handle, 0, 0, XPixel, YPixel,
bitmap.Canvas.handle, 0, 0, srcand);
你明确地调用了Masterbitmap.Canvas.Lock,但你没有调用bitmap.Canvas.Lock(所以你可以在这个调用中随时松开画布句柄......)
此外,您需要考虑GDI本身的线程安全性:应该不惜一切代价避免在不同线程之间共享任何GDI对象。例如,如果您同时在两个不同的设备上下文中选择一个位图(但在不同的线程中),您可能会遇到GDI本身的问题......
请注意旧版本的delphi不能防止缓存句柄的共享(字体,笔刷和笔柄都缓存在全局列表中。如果我没记错的话,这在XE3服务包中得到了修复。)
简而言之:如果您真的需要多线程,我会考虑完全避免使用TCanvas和TBitmap。 (以这种方式安全多线程要容易得多)