从 GTK# 线程访问 System.Drawing.Bitmap 会抛出 Object Current in use other 异常

2023-12-20

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

所以我在这里看了一下 GTK 中的多线程http://www.mono-project.com/docs/gui/gtksharp/responsive-applications/ 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

Update 2

性能下降的解决方案

正如 @voo 所建议的,替换全局位图有助于解决问题。我所做的是而不是使用全局位图。我创建了一个全局字符串(文件名)。现在我使用img=new Bitmap(filename)尝试快速执行,因为我不能出现错误。因此,为了更新 GUI,我使用了此处建议的调用mono-project.com/docs/gui/gtksharp/responsive-applications/ http://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 

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

在GDI中操作位图图像时,幕后有BitmapData需要锁定和解锁。这种机制只是使图片在内存中可供读/写。但是据我所知,当您锁定已锁定的 BitmapData 时,您会得到类似的异常:System.InvalidOperationException,位图区域已被锁定。

对我来说,听起来您遇到了这种错误,但换句话说,因为您没有显式锁定位图数据位。 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...
       }
  }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 GTK# 线程访问 System.Drawing.Bitmap 会抛出 Object Current in use other 异常 的相关文章

随机推荐