tec*_*hno 6 c# gtk mono multithreading 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
}
Run Code Online (Sandbox Code Playgroud)
它的工作效果不如后台工作者抛出当前正在使用的对象其他地方错误,image=new Bitmap(backupimage);这时文本框中的输入速度甚至有点快.我做错了什么?
更新1:
我没有使用同时执行2个不同操作的2个不同线程来处理相同的图像.我在旧线程完成之前调用执行相同操作的线程.在后台工作者中我需要一种方法来检查旧线程已经完成工作,然后启动新的.所以我基本上正在寻找是一种方法来检查同一个线程的实例是否正在运行.在winforms我曾经做过 if(backgroundworker.isbusy==false) then do stuff
更新2
性能下降的解决方案
正如@voo建议更换全局位图有助于解决问题.我所做的不是使用全局位图.我创建了一个全局字符串(文件名).现在我使用img=new Bitmap(filename).Tried执行快速,因为我没有错误出现.所以有序更新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
Run Code Online (Sandbox Code Playgroud)
这里的问题是,您同时在两个地方(两个线程)处理图像,而 .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...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
662 次 |
| 最近记录: |