麻烦锁定线程之间的图像 [英] Trouble with locking an image between threads

查看:106
本文介绍了麻烦锁定线程之间的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要获得在两个不同的线程的锁以访问一个位图(这是从一个摄像头填充)在EmguCv。
我有查询相机并把它返回到.NET位图的getFrame功能。我有两个线程这就需要访问该位图,需要写位图和分配位图到一个图片框,以及其他需要读取位图,将其转换为一个Image对象并将其赋值给一个EMGU ImageBox。
我上的任意对象首先锁定,然后我做我的作业。代码如下(_Camera.LiveFrame是位图):

I need to obtain a lock in two different threads in order to access a Bitmap (which is populated from a webcam) in EmguCv. I have a "GetFrame" functions that queries the camera and places what it returns into a .NET Bitmap. I have two threads which need to access this Bitmap, one needs to write to the Bitmap and assign the Bitmap to a picture box, and the other needs to read the Bitmap, convert it to an Image object and assign that to an EMGU ImageBox. I first lock on an arbitrary Object, then I do my operations. The code is as follows (_Camera.LiveFrame is the Bitmap):

写入/读取主题:

while (_CaptureThreadRunning)
{
   lock (_Camera)
   { 
      // _Camera.GetFrame writes to the Bitmap
      if (_VideoPlaying && _Camera.GetFrame(500)) 
           pbLiveFeed.Invalidate();
    }
}
_Camera.CloseCamera(true);
_CaptureExitEvent.Set();           // Set to signal captureThread has finished



阅读/ ImageBox主题:

Reading/ImageBox Thread:

while (_ProcessThreadRunning)
{
   lock (_Camera)
   {
      //  _Camera.LiveFrame is the Bitmap
      procImage = new Image<Bgr, int>((Bitmap)_Camera.LiveFrame.Clone());          
      procImage.Draw(new Rectangle(10,20,20,15),new Bgr(Color.LightGreen), 5);

      ibProcessed.Image = procImage;
      ibProcessed.Invalidate();
    }
}
_ProcessExitEvent.Set();

这运行正常的大部分时间,但每一个现在,然后我得到一个对象是在其他地方使用当我尝试错误的clone()位图。这难道不是锁定的正确方法?我不明白为什么这会导致问题。

This runs fine most of the time but every now and then I get a "Object is in use elsewhere" error when I try to Clone() the Bitmap. Is this not the proper way to lock? I don't see why this would cause a problem.

PS。我的主题不能再退出优雅无论是。我的。设置()调用之外我回路不会被调用。我猜的线程就被死锁

ps. My threads can no longer exit gracefully either. My .Set() calls outside of my loops are never called. I am guessing the threads are deadlocked?

推荐答案

GDI +有一个锁定机制,防止两个线程使用Bitmap对象 - 这就是你收到的错误。

GDI+ has a locking mechanism which prevents two threads from using a Bitmap object--this is the error you're receiving.

您试图访问该位图,而UI线程已经访问它。例如,1)你的位图分配给图片框,2)图片框废止及然后重画,3)退出写/读线锁定,然后4)读/ imagebox线程试图访问同一位图而重绘仍然发生。

You are trying to access the bitmap while the UI thread is already accessing it. For example, 1) you assign the bitmap to the picture box, 2) the picture box invalidates and then repaints, 3) you exit the write/read thread lock, and then 4) the reading/imagebox thread is trying to access the same Bitmap while the repainting is still occurring.

要解决这个问题,才使位图的副本,并使用该副本来操作。 。无论你给的图片框,不要以为你可以从一个非UI线程再次触摸

To solve the problem, just make a copy of the bitmap, and use that copy to manipulate. Whatever you give the picture box, don't assume you can touch that again from a non-UI thread.

例如,在_Camera.GetFrame:

For example, in _Camera.GetFrame:

// Get the bitmap from the camera
capturedBitmap = GetFromCamera();

// Clone the bitmap first before assigning to the picture box
_Camera.LiveFrame = new Bitmap(capturedBitmap);

// Assign to the picture box
pbLiveFeed.Image = capturedBitmap;

现在,_Camera.LiveFrame应该从线程访问,只要你有适当的锁定。

Now, _Camera.LiveFrame should be accessible from the thread, as long as you have proper locking.

一对夫妇的其他问题,我会考虑在这里:

A couple of other issues I would think about here:


  1. 你提到你是一个任意对象有关锁定,但_Camera似乎是什么,但 - 它是在其他地方可能以不可预知的方式使用的对象。我会建议做它仅用于锁定,例如对象

  1. You mention you are locking on an "arbitrary object", but _Camera seems to be anything but that--it is an object which could be used elsewhere in unpredictable ways. I would suggest making an object which is only used for locking, e.g.

object lockObject = new lockObject;
lock (lockObject)
{
    // put your synchronized code here
}


  • Bitmap.Clone()创建了这股像素数据与原始位的位图。当您转换为图像对象分配给EMGU ImageBox,您使用的克隆,它保持对位图的引用。因此,它似乎更安全,我只需要创建一个新的位图,而不是在这种情况下使用的clone()。

  • Bitmap.Clone() creates a bitmap which shares pixel data with the original bitmap. When you convert to the image object to assign to the EMGU ImageBox, you are using that clone, which maintains a reference to the bitmap. So, it seems safer to me to just create a new bitmap, rather than to use Clone() in this case.

    这篇关于麻烦锁定线程之间的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆