【发布时间】:2014-11-23 12:46:48
【问题描述】:
我对 Delphi 有一些问题。
我编写了两个简单的函数来制作屏幕截图,将其转换为 jpeg 并解码为 base64 流。 如果我在主流节目中制作它,它的效果很好。但是如果我创建一个 TThread 类并在 Execute 上启动这个函数,windows 会冻结,我只能重新启动我的电脑。
通过多次尝试,我发现通过程序JpegImg.SaveToStream(Input);挂起PC
如果我不将 Bitmap 转换为 jpeg,它的效果很好,我会得到图像字符串。
请帮忙。
这里有代码
procedure TEvReader.ScreenShot(DestBitmap : TBitmap) ;
var DC : HDC;
begin DC := GetDC (GetDesktopWindow) ;
try
DestBitmap.Width := GetDeviceCaps (DC, HORZRES) ;
DestBitmap.Height := GetDeviceCaps (DC, VERTRES) ;
BitBlt(DestBitmap.Canvas.Handle, 0, 0, DestBitmap.Width, DestBitmap.Height, DC, 0, 0, SRCCOPY) ;
finally
ReleaseDC (GetDesktopWindow, DC) ;
end;
end;
function TEvReader.Base64FromBitmap(Bitmap: TBitmap): string;
var
Input: TBytesStream;
Output: TStringStream;
JpegImg:TJPEGImage;
begin
Input := TBytesStream.Create;
try
JpegImg:=TJPEGImage.Create;
JpegImg.Assign(Bitmap);
JpegImg.SaveToStream(Input); {here a problem.When i replace "JpegImg" to "Bitmap" all works good }
Input.Position := 0;
Output := TStringStream.Create('', TEncoding.ASCII);
try
Soap.EncdDecd.EncodeStream(Input, Output);
Result := Output.DataString;
finally
Output.Free;
end;
finally
Input.Free;
end;
end;
procedure TOutThread.Execute;
var
bmp:TBitmap;
strrr:String;
begin
bmp:=TBitmap.Create;
mObj.ScreenShot(bmp);
strrr := mObj.Base64FromBitmap(bmp);
Form2.Memo4.Text := strrr;
end;
【问题讨论】:
-
我猜,但这可能会有所帮助:qc.embarcadero.com/wc/qcmain.aspx?d=55871。位图不是线程安全的。你需要锁定/解锁它的画布。
-
@kobik 听起来好像他从多个线程访问同一个位图对象。或者 VCL 位图是否有一些疯狂的实现?
-
@DavidHeffernan TJPEGImage 搞砸了,它的 Bitmap.Canvas DC 存在问题,有时由于 graphics.pas 中的 GDI 对象缓存机制而被清除
-
@David,问题是从与主 UI 不同的线程访问位图 DC。除非被锁定,否则主 UI WndProc 将销毁 DC。
-
@kobik 这太奇怪了。我无法想象他们脑子里在想什么。有时我想知道 Embarcadero 的开发人员是否知道线程存在。我从来没有克服过
Set8087CW不是线程安全的事实,仍然不是线程安全的。
标签: delphi bitmap base64 tthread