从 GTK# 访问 System.Drawing.Bitmap 线程抛出当前在其他地方使用的对象异常

本文关键字:其他 方使用 异常 对象 System 访问 GTK# Drawing Bitmap 线程 | 更新日期: 2023-09-27 18:36:22

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

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

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 个不同的操作来处理相同的图像。我调用在旧线程完成之前执行相同操作的线程。与后台工作线程一样,我需要一种方法来检查旧线程是否已在启动新线程之前完成工作。所以基本上im正在寻找的是一种检查同一线程的实例是否的方法正在运行。在温沃斯,我曾经做过if(backgroundworker.isbusy==false) then do stuff

更新 2

性能下降的解决方案

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

在大图像处理操作方法结束时,我添加了它以更新 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 

从 GTK# 访问 System.Drawing.Bitmap 线程抛出当前在其他地方使用的对象异常

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

在 GDI 中操作位图图像时,幕后有位图数据需要锁定和解锁。这种机制只是使图片在内存中可用于读/写。但是AFAIK当你锁定已经锁定的BitmapData时,你会得到一个类似的异常: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...
       }
  }