2015-01-06 2 views
6

Im пытается манипулировать изображением с помощью system.drawing в GTk #. Я хочу, чтобы пользовательский интерфейс обновлял изображение на экране, как только пользователь обновляет текстовое поле. Чтобы реализовать это, я попытался использовать фонового рабочего из winforms, он работал, но когда текстовое поле обновляется с большей скоростью, приложение застревает без ошибок.Доступ к System.Drawing.Bitmap из GTK # Thread throws Object В настоящее время используется в другом месте Исключение

Итак, я посмотрел на многопоточность в 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);, когда скорость записи в текстовом поле даже немного fast.What им я делаю неправильно?

Update 1:

Im не обрабатывает один и тот же образ, используя 2 различных потоков, что делает 2 различных операций, в то же time.Im вызывая поток, который делает ту же операцию, прежде чем старая нить завершена . Как в фоновом работнике, мне нужен способ проверить, завершил ли старый поток работу перед запуском новой. Так что в основном то, что искал, - это способ проверить, работает ли экземпляр того же потока . В winforms я использовал if(backgroundworker.isbusy==false) then do stuff

Update 2

Решение с деградацией производительности

Как было предложено @voo Замена глобального растрового изображения помогли решить issue.What я сделал вместо использования глобальной bitmap.I создана глобальная string (filename). Теперь я использую 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 
+0

Я буду использовать мой хрустальный шар (потому что не знаю, о GTK вообще) и сказать, что GTK, как почти любой другой инструментарий UI не любит обновление GUI из потока, отличного от основного потока, и позволяет каким-то образом запускать очереди на главной трассе, дорогие вычисления завершены. – Voo

+0

@ Voo Я не обновляю пользовательский интерфейс в потоке. Я просто обрабатываю изображение. – techno

+0

Можете ли вы использовать точное исключение? Я просто grep-ped как libgdiplus, так и моноисточники, и я не мог найти ссылок на предоставленный вами текст. Или вы работаете в Windows? – fog

ответ

3

Проблема здесь состоит в том, что вы обрабатываете изображение в двух местах (две нити) на то же самое время и изображения работа в .Net (GDI) не позволяет этого. Потому что вы не предоставили очень много информации, я просто угадываю здесь.

При манипулировании растровыми изображениями в GDI за сценой находятся битмап-данные, которые необходимо заблокировать и разблокировать. Этот механизм просто делает изображение доступным в памяти для чтения/записи. Но AFAIK, когда вы блокируете BitmapData, который уже заблокирован, вы получаете аналогичное исключение: System.InvalidOperationException, область Bitmap уже заблокирована.

Для меня это похоже на то, что вы получаете такую ​​ошибку, но с другими словами, потому что вы явно не блокируете биты битмартных данных. GDI просто скажет вам: «Мне нужно заблокировать биты битмап-данных, но я не могу, потому что объект уже используется (заблокирован) в другом месте."

Решение здесь может быть, чтобы попытаться синхронизировать использование растровых изображений (где биты запирающие могут быть вовлечены) между нитью всякий раз, когда они могут произойти Таким образом, вы можете использовать блокировки ключевое слово или аналогичный механизм:.

Так попробовать что-то, что выглядит следующим образом:

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... 
     } 
    } 
+0

Спасибо за ответ. Я не обрабатываю одно и то же изображение, используя 2 разных потока, которые выполняют 2 разных операции одновременно. Я вызываю поток, который выполняет ту же операцию до завершения старого потока. Как в фоновом работнике мне нужен способ чтобы проверить, завершил ли старый поток работу перед запуском новой. В основном, что ищет, это способ проверить, работает ли экземпляр того же потока. – techno

+0

Вы, кажется, говорите, что «новый» поток работает, пока «старый» поток еще не закончен. Если это так, вы можете обрабатывать изображение в двух разных потоках. Кстати, если вы не хотите распараллеливать (threading) обработку между «новыми» и «старыми» потоками, вам может не понадобиться использовать потоки здесь. Тем не менее, если вы попытаетесь заблокировать раздел обработки растровых изображений в своем «старом» и «новом» потоке, мое решение должно предотвратить возникновение исключения. И это смешно, потому что сегодня у меня было такое же исключение в проекте, который я разрабатываю, и я решил его, синхронизируя потоки с ключевым словом блокировки ;-) –

+0

Я не понимаю, как работает этот механизм блокировки. Что именно происходит с блокировкой изображения делает блокировка (imagelock) делаю. Вы видели мое обновление # 2 – techno