TCanvas 的问题(100分)

  • 主题发起人 主题发起人 andin
  • 开始时间 开始时间
A

andin

Unregistered / Unconfirmed
GUEST, unregistred user!
在 Delphi5 下开发了一个程序,其中有一段程序是这样的:

InsertBmp.Width := FCurrentBitmap.Width;
InsertBmp.Height := FCurrentBitmap.Height;
InsertBmp.Canvas.Draw(0,0,FCurrentBitmap);
InsertBmp.PixelFormat := tempBMP.PixelFormat;
InsertBmp.SaveToStream(..);

在一个工作线程内,不断得调用这段程序,将 FCurrentBitmap 数据拷贝到 InsertBmp 对象之中,可是奇怪的是,偶尔,这样的拷贝(Draw)不成功,也就是说,偶尔拷贝后的InsertBmp 是一片空白,但是 FCurrentBitmap 却有数据!!!
 
调用线程是不是用Synchronize方法
 
在同一个线程内调用,应当说,调用 Synchronize 这是没有必要的
 
用assign试试
 
Assign 办法我也试过,Delphi6 我也试过,都存在同样的问题!
CopyRect 方法我也试过,都不行,大家可以作个试验验证这个问题!

由此看来,Delphi 并不适合作多媒体方面软件开发!只适合作数据库方面开发。
 
>>偶尔拷贝后的InsertBmp 是一片空白,但是 FCurrentBitmap 却有数据
你用什么方法判断的?
 
同时将 InsertBmp 以及 FCurrentBitmap 输出到文件,就会发现这种不一致的现象
 
按理说assign出来的对象如果不修改的话与原对象使用的是一个地址啊。
不应该不一样啊,再不行,在assign之前,加上insertbmp:=nil; 你把insertbmp
和fcurrentbitmap的地址输出看看,是不是指向同一个地方?
 
千万不要用 Assign !Assign 办法并没有拷贝数据,只是将 FBitmapImage 的 RefCount 递增了。
如果非要这样作,必然导致这个奇怪的异常:Out of System Resource,Graphic.pas 代码我还没有完全看明白,只知道是因为申请 GDI 资源时,失败了,导致这个异常,可是为什么会失败,我还没有看明白。
可以肯定的是,Graphic.pas 文件肯定有 Bug,目前我得到这么一个规律:在一个工作线程内,对一个TBitmap 对象进行 DDB 与 DIB 间转换若干次后,必然导致 GDI 资源泄漏,从而引起 Out of System Resource 异常。如何修复这个 Bug 。。。。。?
 
看来你的在insertbmp中做了别的操作,否则不会出现上述错误的。这个问题好像帮不上
忙了。不过,我觉得如果觉得tbitmap有内存泄漏的话,还是干脆直接用api函数得了,
内存泄漏这种错误找起来挺麻烦的。
 
我也没有用 InsertBmp 干别的事情,只是将这个 TBitmap 对象输出到一个 TStream 对象中,输出完毕后,就释放了 InsertBmp 对象,下次用的时候,再重新申请这个对象;
程序非常简单,应当是没有错误的。

直接用API作,比较麻烦,需要自己编写程序将一个 DDB 对象转换为 DIB 对象,这是没有办法的办法了;
 
如果是这样的话,问什么不直接用FCurrentBitmap.savetostream呢?是不是在assign
后fcurrentbitmap操作时出错误呢?每在线成里用过tbitmap,说不清楚,不过,我觉得
tbitmap不一定是线程安全的,所以,最好用一下Synchronize
 
如果直接用 FCurrentBitmap.SaveToStream,这个线程运行不到五分钟,这个地方就出现
Out of system resource 异常!

这个问题搞得我非常非常的痛苦,真恨不得彻底的抛弃 Delphi !
 
你在draw之前,要lock, draw了后,要unlock(如果你在线程中的话)
 
无论怎么 Lock ,都不管用
 
你的FCurrentBitmap很可疑啊!他得知从哪里来呢?是不是用了主线程的资源?
 
你要确定FCurrentBitmap不会被多个线程访问才不用调用Synchronize
如果仅仅是SaveToStream,建议还是直接用FCurrentBitmap才好,如果也会出错,建议仔细检查代码
出错一般讲还是自己的代码有问题,大部分人还是发现不了Delphi原生VCL源码的错误的,而且正确性也是相对的,在一定的使用条件下才会正确,VC里边你要是东西没正确使用,会比Delphi下更惨,那时可能大多是人还是会相信自己的代码出错.
 
如果还错,你只能把InsertBmp.Canvas.Draw(0,0,FCurrentBitmap)通过Synchronize插入到主线程了,这样就不会有问题了
 
用 Synchronize 的方法,我也试过,还是不行,现象就是:虽然 Draw 方法没有报告异常,但是经常执行不成功,得到的 InsertBmp 只是空白的一张图片;
 
谢谢 zjan521 对我的提醒,我也不敢轻易怀疑 Delphi 有问题,毕竟有这么多的开发者在使用。可是,类似这样的问题,出现过很多次,而且我的程序非常的简单,肯定不会出现错误。
如果大家对这个可能的 Delphi bug 感兴趣,留下Email,我将演示程序发送给你们,我们一起来看,这个问题是如何发生的!
 
后退
顶部