从GTK访问System.Drawing.Bitmap #Thread抛出Object目前在其他地方使用异常

时间:2015-01-06 16:43:48

标签: c# multithreading mono gtk gtk#

我试图在GTk中使用system.drawing来操作图像#。我希望UI在用户更新文本框后立即在屏幕上更新图像。为了实现这一点,我尝试使用winforms的后台工作程序,它工作了但是当文本框以更高的速度更新时,应用程序就会陷入失误状态。

所以我在这里看了一下GTK中的多线程http://www.mono-project.com/docs/gui/gtksharp/responsive-applications/并创建了一个线程。

void textboxchanged()
{
    Thread thr = new Thread (new ThreadStart (ThreadRoutine));
    thr.Start ();

  }

  static void ThreadRoutine ()
  {
        LargeComputation ();

  }

  static void LargeComputation ()
  {
    image=new Bitmap(backupimage);
   //Long image processing 
  }

它的效果不如后台工作者抛出当前正在使用的对象其他地方错误image=new Bitmap(backupimage);当文本框中的输入速度甚至有点快时。我做错了什么?

更新1:

我没有使用同时执行2个不同操作的2个不同线程来处理相同的图像。我在旧线程完成之前调用执行相同操作的线程。在后台工作者中我需要一种方法来检查是否旧线程在启动新线程之前已经完成了工作。所以我基本上正在寻找的是一种检查同一线程的实例的方法 正在运行。在winforms我曾经做过if(backgroundworker.isbusy==false) then do stuff

更新2

性能下降的解决方案

根据@voo的建议更换全局位图有助于解决问题。我所做的不是使用全局位图。我创建了一个全局字符串(文件名)。现在我使用img=new Bitmap(filename)。尝试快速执行,因为我因此,为了更新GUI,我按照mono-project.com/docs/gui/gtksharp/responsive-applications/的建议使用了调用。事情是没有出现错误并且图像得到更新,但是当打字操作足够快时会出现等待。性能降低了。后台工作人员的情况并非如此。有没有办法提高性能。

在大图像处理操作方法结束时,我将其添加到更新GUI

Gtk.Application.Invoke (delegate {

            MemoryStream istream=new MemoryStream();
            img.Save (istream, System.Drawing.Imaging.ImageFormat.Png);
            istream.Position = 0;
            workimagepixbuff = new Gdk.Pixbuf (istream);
            image1.Pixbuf = workimagepixbuff.ScaleSimple (400, 300, Gdk.InterpType.Bilinear);

        });
        // cannot directly convert Bitmap to Pixbuff,so doing this 

1 个答案:

答案 0 :(得分:3)

这里的问题是你在同一时间处理两个地方(两个线程)的图像,而.Net(GDI说话)中的图像操作不允许这样做。 因为你没有提供太多信息,我只是在这里猜测。

在GDI中操作位图图像时,场景后面的BitmapData需要锁定和解锁。这种机制只是使图像在内存中可用于读/写。但是当您锁定已经锁定的BitmapData时AFAIK会出现类似的异常:System.InvalidOperationException,Bitmap区域已被锁定。

对我而言,听起来你会遇到这种错误,但换句话说,因为你没有明确地锁定位图数据位。 GDI只是告诉你:“我必须锁定位图数据位,但我不能,因为该对象已在其他地方使用过(锁定)。”

这里的解决方案可能是尝试在线程之间尝试同步位图使用(可能涉及位锁定)。因此,您可能需要使用 lock 关键字或类似机制:

请尝试以下内容:

private static object _imageLock = new object();
static void LargeComputation ()
  {
     lock(_imageLock)
     {
       image=new Bitmap(backupimage);
       //Long image processing ...
     }
  }

  static void AnotherImageOperationSomewhereElse()
  {
       lock(_imageLock)
       {
          //Another image processing on backupImage or something derived from it...
       }
  }
相关问题