使用C#异步处理位图对象

3
我正在尝试在多个线程中处理位图对象。我在UI线程中创建该对象,并希望异步保存它。在调用保存方法后,我继续以几种方式处理和操作位图。

当主线程修改位图时,异步线程会抛出错误或破坏流。我尝试使用async/await和ThreadStart实现,但两者的结果都相同。

我已经通过复制位图流并将新流发送到异步方法来解决这个问题,但这会导致性能损失。特别是在处理大型流时,复制几乎需要保存时间的一半。

我想知道是否有人对这种情况有解决方法。

2个回答

6
我假设这个问题是关于 System.Drawing.Bitmap 类的。几乎任何对位图的非平凡操作都会在幕后调用相当于 Bitmap.LockBits() 的方法。其中包括 Image.Save()、Graphics.FromImage()、Bitmap.SetPixel() 等等。该锁只能由一个线程持有,任何试图锁定位图的其他线程将触发异常。
因此,完全由您来确保没有两个线程可以同时访问该位图。换句话说,您必须在代码中使用 lock 关键字确保在位图正在使用时阻止线程。请注意,这会导致不可避免的并发丢失,如果 UI 线程在同一时间想要绘制位图,则它将被阻塞,而工作线程则在 tinkers with the bitmap。
请注意,这并非总是可能的。例如,您无法更改 PictureBox 类以插入所需的锁定。背景图片属性也是如此。等等。这意味着您不能再使用这些方便的类/属性,您必须自己处理绘制,以便插入锁定。

谢谢你的回答,汉斯。我尝试了锁定,但我的考虑是性能。锁定位图会使事情变得更慢,甚至比单线程工作还要慢(正如你所指出的)。我想在处理大型流时必须忍受这种性能下降。 - Kerem Demirer

3

第一个链接非常棒,但是需要澄清的是,“异步”的部分只是其中的一小部分,更加强调的是不安全编程的优势。 - KansaiRobot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接