简体   繁体   English

用c#异步处理位图对象

[英]Processing Bitmap object asynchronously with c#

What I'm trying to process a bitmap object in several threads.我试图在多个线程中处理位图对象。 I create the object in UI thread and want to save it asynchronously.我在 UI 线程中创建对象并希望异步保存它。 After save method is called, I continue to process the bitmap and manipulate it in several ways.调用 save 方法后,我继续处理位图并通过多种方式对其进行操作。

When the main thread modifies the bitmap, async thread throws an error or corrupts the stream.当主线程修改位图时,异步线程会抛出错误或破坏流。 I tried to use async/await and ThreadStart implementations, both results are same.我尝试使用 async/await 和 ThreadStart 实现,结果是一样的。

I've been able to fix this by copying bitmap stream and send the new stream to async method but this has a performance penalty.我已经能够通过复制位图流并将新流发送到异步方法来解决这个问题,但这会降低性能。 Copying it almost takes the half time of the saving it, especially when working with large streams.复制它几乎需要保存它的一半时间,尤其是在处理大流时。

I wondered if anybody have a workaround for this scenario.我想知道是否有人对这种情况有解决方法。

I'll assume this question is about the System.Drawing.Bitmap class.我假设这个问题是关于 System.Drawing.Bitmap 类。 Almost any non-trivial operation on the bitmap calls the equivalent of Bitmap.LockBits() under the hood.几乎所有对位图的非平凡操作都在后台调用了等效的 Bitmap.LockBits()。 This includes Image.Save(), Graphics.FromImage(), Bitmap.SetPixel() etcetera.这包括 Image.Save()、Graphics.FromImage()、Bitmap.SetPixel() 等。 This lock can be held by only one thread at a time.该锁一次只能由一个线程持有。 Any other thread that tries to lock the bitmap will trigger the exception.任何其他试图锁定位图的线程都会触发异常。

It is therefore entirely up to you to ensure that no two threads can access the bitmap at the same time.因此,完全由您来确保没有两个线程可以同时访问位图。 In other words, you must use the lock keyword in your code to ensure that a thread is blocked when the bitmap is in use.换句话说,您必须在代码中使用lock关键字以确保在使用位图时线程被阻塞。 Do note the inevitable loss of concurrency you'll get from this, your UI thread will be stalled while your worker thread tinkers with the bitmap if it happens to want to paint the bitmap at the same time.请注意您将从中获得的不可避免的并发损失,如果您的工作线程碰巧想要同时绘制位图,则您的 UI 线程将停止,而您的工作线程会修补位图。

Do beware that this is not always possible.请注意,这并不总是可能的。 You for example cannot alter the PictureBox class to insert the required lock .例如,您无法更改 PictureBox 类以插入所需的lock Same story for the BackgroundImage property. BackgroundImage 属性也是如此。 Etcetera.等等。 With the consequence that you cannot use these convenience classes/properties anymore, you have to take care of painting yourself so you can insert the lock.结果是你不能再使用这些便利的类/属性,你必须自己画画,这样你才能插入锁。

You can use the Parallel class in System.Threading.Tasks namespace.您可以使用 System.Threading.Tasks 命名空间中的 Parallel 类。 Following link has some samples and explanations.以下链接有一些示例和解释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM