线程图像缩放子仍然阻碍了UI

时间:2009-04-30 20:01:34

标签: .net vb.net multithreading graphics

我为我的老板创建了一个图像查看控件,它包含平移,通过鼠标滚轮缩放,以及绘制一个缩放的框。控件需要支持非常大的图像文件(即每侧数千个像素)。

一切正常,但只要代码缩放图像,控件UI就会无法响应。我的老板让我使用线程将缩放代码设置为与UI分开。扩展代码现在肯定是在一个单独的线程上,但在扩展代码运行时UI仍然陷入困境!谁能帮帮我呢?

以下是缩放代码。如果这还不足以帮助我,请告诉我,我会发布您需要的任何代码!

更新:这是完整的控制代码。 link text

4 个答案:

答案 0 :(得分:0)

我怀疑由于缩放是使用UI正在阻止的所有CPU。两个线程可能都处于相同的优先级。

尝试降低扩展线程的优先级,以允许UI响应。

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

答案 1 :(得分:0)

请尝试使用此功能。

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以异步方式运行它。

编辑 - 请参阅上面的更正。 EndScaleImage的ar参数应该声明为ByRef,也应该是BeginScaleImage的img参数。他们没有理由通过ByVal !!

答案 2 :(得分:0)

您的Image Scaled()如何将图像显示回UI?

答案 3 :(得分:0)

似乎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 );
    }
}

如果无限循环已经空了,则CPU使用率超过90%,因此它们使用了我的CPU的两个核心。如果存在FillRectangle,则使用率略低于50%,表示只有一个线程可以在运行时运行它。

因此,在缩放过程中,您可以从GUI线程进行的任何GDI +调用都可能会阻塞,直到缩放完成为止。