Подпрограмма масштабирования изображения с резьбой все еще не работает - PullRequest
1 голос
/ 01 мая 2009

Я создал элемент управления просмотром изображения для моего босса, который включает в себя панорамирование, масштабирование с помощью колесика мыши и рисование поля для увеличения. Элемент управления должен поддерживать очень большие файлы изображений (т.е. несколько тысяч пикселей с каждой стороны).

Все это работает, но всякий раз, когда код масштабирует изображение, пользовательский интерфейс управления перестает отвечать на запросы. Мой босс заставил меня использовать многопоточность, чтобы установить код масштабирования отдельно от пользовательского интерфейса. Код масштабирования теперь определенно находится в отдельном потоке, но пользовательский интерфейс все еще не работает во время выполнения кода масштабирования! Может кто-нибудь, пожалуйста, помогите мне с этим ??

Ниже приведен код масштабирования. Дайте мне знать, если этого недостаточно, чтобы помочь мне, и я выложу любой код, который вам нужен!

ОБНОВЛЕНИЕ: вот полный контрольный код. текст ссылки

Ответы [ 4 ]

0 голосов
/ 01 мая 2009

Похоже, что есть некоторая глобальная блокировка в GDI + API. Для теста я создал две темы на основе следующей функции

static void test_thread()
{
    Bitmap bmp = new Bitmap( 4000, 4000 );
    Graphics g = Graphics.FromImage( bmp );
    Brush b = Brushes.Red ;

    for ( ; ; ) {
        g.FillRectangle( b, 0, 0, bmp.Width, bmp.Height );
    }
}

Если бесконечный цикл оставлен пустым, загрузка процессора превысила 90%, поэтому они использовали оба ядра моего процессора. При наличии FillRectangle его использование было немного ниже 50%, что указывает на то, что только один поток может его запустить одновременно.

Таким образом, возможно, что любой вызов GDI +, который вы делаете из потока GUI, пока идет масштабирование, будет блокироваться до завершения масштабирования.

0 голосов
/ 01 мая 2009

Попробуйте использовать это вместо.

Private Sub Worker(object o)
    Dim args as ScaleImageArguments
    args = CType(o, ScaleImageArguments) 
    ScaleImage(args)
End Sub

Private Sub RunScaleImageAsync(ByVal img As Image, ByVal scale As Double)
    System.Threading.ThreadPool.QueueUserWorkItem(Worker, _
                 New ScaleImageArguments(img.Clone, scale))
End Sub

ALTERNATIVE - Использование асинхронного шаблона.

Private Delegate Sub ScaleImageDelegate(ByRef arg As ScaleImageArguments)

Private Sub BeginScaleImage(ByRef img As Image, ByVal scale As Double)
    Dim d As ScaleImageDelegate
    d = New ScaleImageDelegate(AddressOf ScaleImage)

    d.BeginInvoke(New ScaleImageArguments(img.Clone, scale), _
                  New AsyncCallback(AddressOf EndScaleImage), d)        
End Sub

Private Sub EndScaleImage(ar As IAsyncResult)
    Dim d As ScaleImageDelegate
    d = CType(ar.AsyncState, ScaleImageDelegate)
    d.EndInvoke(ar)
End Sub

Затем просто вызовите BeginScaleImage, чтобы запустить его асинхронно.

РЕДАКТИРОВАТЬ - Пожалуйста, смотрите исправления выше. Аргумент ar в EndScaleImage должен быть объявлен ByRef, а также в качестве img-параметра BeginScaleImage. Нет причин, по которым их следует передавать ByVal !!

0 голосов
/ 01 мая 2009

Как ваш ImageScaled () отображает изображение обратно в пользовательский интерфейс?

0 голосов
/ 01 мая 2009

Я подозреваю, что, поскольку для масштабирования используется весь процессор, который заболел пользовательский интерфейс. Оба потока, вероятно, имеют одинаковый приоритет.

Попробуйте уменьшить приоритет потока масштабирования, чтобы пользовательский интерфейс реагировал.

Values for Thread Priority:

Above Normal -> Gives thread higher priority
Below Normal ->Gives thread lower priority
Normal -> Gives thread normal priority
Lowest -> Gives thread lowest priority
Highest -> Gives thread highest priority

so you would probably use:

Thread1.Priority=System.Threading.ThreadPriority.BelowNormal
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...