被释放的句柄以某种方式被破坏了?

Tal*_*Guy 5 delphi handles

奇怪的问题.也许有人可以提供一些见解.

  • 场景1.我在内存中有一个写入的TBitmap,同时进行复杂的计算以计算每个像素的颜色.每隔一段时间(通常在填充位图的每条水平线之后)TBitmap都会被绘制到窗体上的图像(image1.Canvas.Draw(0,0,TBitmap).大部分时间这都工作正常,但我注意到了如果每个位图行有很多缓慢的复杂计算(比如计算时间超过30秒或一分钟),那么主表单会有一个瞬间"闪烁",以某种方式擦除位图,因此image.draw调用只绘制最新计算的行和前y行在位图中被消隐.我通过在计算之前锁定位图来解决这个问题.

  • 情景2. 这是主要的麻烦.我写的是TMemoryStream而不是位图.同样的交易.进行计算以计算每个像素值,然后在处理过程中使用memstream.Write(bytevalue,1)将每个像素值写入TMemoryStream.在所有计算结束时,我使用memstream.SaveToFile('whatever.bmp')将流保存到位图,然后使用memstream.Free释放流.如果计算速度很快,那么无论大小如何,流都会保存(我正在使用10000x10000尺寸进行测试).

我甚至可以判断生成的文件是否会损坏,因为主应用程序窗口/窗体确实有轻微的闪烁,就像它被重新绘制一样.当发生这种情况时,就好像每个位图和TMemoryStream句柄都被杀死/刷新,因此现有数据已损坏.

有任何想法吗?这真的很糟糕.特别是当每个单个图像可能需要一个小时来创建时才发现它在后台发生了某些事情并且损坏了位图或TMemoryStream.

我有没有办法像位图一样锁定TMemoryStream句柄?这可能有所帮助.或者一些声明告诉Delphi"不要弄乱我的对象,即使看起来应用程序花了太长时间"

或者有没有人知道Delphi中导致这种情况发生的后端原因.

TMemoryStream是在执行所有计算的过程内创建的,因此是本地对象.对于位图问题,位图是程序之外的全局变量,它发生了,所以我不认为这是原因.

这也是在Windows 7下,但我注意到Vista下的原始位图问题.

更新1:

很抱歉没有使用评论,但有文字大小的重新提交...

回复雷米(和其他读这篇文章的人)......

单线程.对于内存流,如果计算速度很快,它可以在5000x5000分辨率下正常工作,但如果cals很慢则会失败.

作为一个基本框架,代码是沿着的

SetupMemorystream; 
for y:=0 to height do 
   for x:=0 to width do 
      DoCalcs;
      SetByteValue; 
   end; 
end; 
SaveStream; 
Run Code Online (Sandbox Code Playgroud)

如果DoCalcs相对快速,那么一切都按计划进行.如果它很慢,那么我得到了TMemoryStream损坏,并且流保存到的结果位图已损坏.

这与使用内存TBitmap相同,直到我发现我可以锁定位图,这会阻止Delphi和/或Windows在"想要"时重新分配新句柄,从而破坏位图内的数据.

考虑到TMemoryStream及其句柄没有发生同样的问题,这太巧合了.

更新2:

还有一点可能是有用的信息.

当TMemoryStream保存OK时,生成的文件(对于5000x5000位图)的大小为75,000,054字节.

当保存的流损坏时,它似乎是一个随机值(从句柄损坏到保存流的大小).示例大小为22 MB和9 MB.

当我查看生成的文件是一个十六进制编辑器时,它显示文件的开头是正确的标题块,但尾部以某种方式被截断.

这太离奇了.无论如何,我可以绝对确保在SaveToFile调用之后和释放它之前刷新TMemoryStream?

Run*_*ner 0

仅通过假设正在发生的事情很难发现这样的错误。由于操作时间太长,如果发现错误就重复并等待,成本高昂。

我建议您记录该过程的每一步。您可能会得到一个巨大的日志,但它会告诉您哪里出了问题。重复这个过程并改进你的日志,这样你就会慢慢但肯定地找到问题的原因。