相关疑难解决方法(0)

GDI在第二个线程中使用TGIFImage处理泄漏

我有一个后台线程加载图像(从磁盘或服务器),目标是最终将它们传递给主线程进行绘制.当第二个线程使用VCL TGIFImage加载GIF图像时,每次在线程中执行以下行时,此程序有时会泄漏几个句柄:

m_poBitmap32->Assign(poGIFImage);
Run Code Online (Sandbox Code Playgroud)

也就是说,刚刚打开的GIF图像被分配给线程拥有的位图.这些都不与任何其他线程共享,即完全本地化到线程.它与时序有关,因此每次执行该行时都不会发生,但是当它确实发生时,它只发生在该行上.每个泄漏都是一个DC,一个调色板和一个位图.(我使用GDIView,它提供比Process Explorer更详细的GDI信息.) m_poBitmap32这是一个Graphics32 TBitmap32对象,但我使用普通的VCL专用类重现了这一点,即使用Graphics::TBitmap::Assign.

最终我得到一个EOutOfResources异常,可能表明桌面堆已满:

:7671b9bc KERNELBASE.RaiseException + 0x58
:40837f2f ; C:\Windows\SysWOW64\vclimg140.bpl
:40837f68 ; C:\Windows\SysWOW64\vclimg140.bpl
:4084459f ; C:\Windows\SysWOW64\vclimg140.bpl
:4084441a vclimg140.@Gifimg@TGIFFrame@Draw$qqrp16Graphics@TCanvasrx11Types@TRectoo + 0x4a
:408495e2 ; C:\Windows\SysWOW64\vclimg140.bpl
:50065465 rtl140.@Classes@TPersistent@Assign$qqrp19Classes@TPersistent + 0x9
:00401C0E TLoadingThread::Execute(this=:00A44970)
Run Code Online (Sandbox Code Playgroud)

如何TGIFImage在后台线程中解决此问题并安全使用?

其次,我会遇到PNG,JPEG或BMP类的同样问题吗?我还没有到目前为止,但鉴于它是一个线程/时间问题并不意味着如果他们使用相似的代码我就不会TGIFImage.

我正在使用C++ Builder 2010(RAD Studio的一部分.)


更多细节

一些研究表明,我不是唯一遇到这种情况的人.引用一个帖子,

Help(2007)说:在使用Lock保护画布的多线程应用程序中,所有使用画布的调用都必须通过调用Lock来保护.在使用之前没有锁定画布的任何线程都会引入潜在的错误.

[...]

但是这个陈述是绝对错误的:即使其他线程没有触摸它,你也必须在辅助线程中锁定画布.否则,画布的GDI句柄可以在主线程中随时释放(异步).

另一个回复表明类似的东西,它可能与graphics.pas中的GDI对象缓存有关.

这很可怕:在一个线程中完全创建和使用的对象可以在主线程中异步释放一些资源.不幸的是,我不知道如何应用Lock建议TGIFImage. TGIFImage没有Canvas,虽然它确实有Bitmap一个画布.锁定无效.我怀疑这个问题实际上是TGIFFrame一个内部课程.我也不知道是否或如何锁定任何TBitmap32资源.我确实尝试将TMemoryBackend位图分配给位图,这避免了使用GDI,但它没有任何效果.

再生产 …

delphi memory-leaks gdi c++builder thread-safety

16
推荐指数
1
解决办法
1560
查看次数

寻找自定义图像网格

我正在尝试找到一个专门用于显示图像的网格.它也需要具有良好的性能,并且最好具有某种缩略图缓存.图像需要从文件加载,如果图像也可以动态分配,那将是很好的.它不应该在标准网格的列/行记录列表上工作,而是单个项目列表,每个项目代表一个图像.应该有一个属性可以同时为所有列和行定义列宽和行高,而不是一次定义一个.最终目标是列出具有用户选项的所有图像,以控制显示图像的大小.它将用作产品展示,因此需要某种自定义绘图功能,如OnDrawItem事件.这可能会在此列表中显示多达50,000个图像,因此TListView无法正常工作,因为它非常重要.

它需要使用Delphi 2010,XE2,最好是7.

以下是如何在下面显示8张图像的3个示例.我并不是说每个图像的大小不同,但大小完全相同.没有2列可以具有不同的宽度,并且与行相同.

在此输入图像描述

delphi grid image delphi-7 delphi-xe2

10
推荐指数
1
解决办法
8946
查看次数

主线程被阻止时显示活动指示符(继续)

继续上一个问题 我希望即使主线程被阻止也能显示一些活动指示.(基于这篇文章).

基于附加代码的问题:

  • 使用Synchronize(PaintTargetWindow);不会绘制窗口
  • 我有时会收到一个错误: Canvas does not allow drawing.在行中:{FBitmap.}StretchDraw(Rect(Left, ImageRect.Top, Right, ImageRect.Bottom), FfgPattern)

这是我用来创建指标线程的代码:

unit AniThread;

interface

uses Windows, Classes, Graphics, Controls, Math;

const
  ANI_GRAD_FG_COLOR_BAGIN = $00CDFFCD;
  ANI_GRAD_FG_COLOR_END   = $0024B105;
  ANI_GRAD_BK_COLOR_BAGIN = $00F5F5F5;
  ANI_GRAD_BK_COLOR_END   = $00BDBDBD;

type
  TAnimationThread = class(TThread)
  private
    FWnd: HWND;
    FPaintRect: TRect;
    FInterval: Integer;
    FfgPattern, FbkPattern: TBitmap;
    FBitmap: TBitmap;
    FImageRect: TRect;
    procedure UpdatePattern(Pattern: TBitmap; ColorBegin, ColorEnd: TColor);
    function CreatePatternBitmap(AColorBegin, AColorEnd: TColor): TBitmap;
    procedure PaintTargetWindow;
  protected
    procedure Execute; …
Run Code Online (Sandbox Code Playgroud)

delphi multithreading thread-safety delphi-5

5
推荐指数
1
解决办法
3126
查看次数