2009-04-30 51 views
1

我为我的老板创建了一个图像查看控件,该控件合并了平移,通过鼠标滚轮缩放以及绘制一个框以进行缩放。该控件需要支持非常大的图像文件(即每边数千像素)。螺纹图像缩放子仍然沉没UI

所有的工作,但每当代码缩放图像的控制UI变得反应迟钝。我的老板让我使用线程来设置除了UI之外的缩放代码。缩放代码现在肯定在单独的线程中,但缩放代码正在运行时UI仍然陷入了困境!任何人都可以请帮助我吗?

下面是缩放代码。让我知道如果这不足以帮助我,我会发布你需要的任何代码!

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

+1

你怎么调用这个方法?你的问题不在这个函数中,而是你试图异步运行它的方式。请发布/描述调用上下文。 – 2009-04-30 20:06:29

+0

滑雪,请尝试我的答案中的最新更新代码。此外,您传递ScaleImageArguments和img参数ByVal。这些应该通过ByRef。虽然这不是线程在执行ScaleImage期间阻塞的原因。 – 2009-04-30 20:52:03

回答

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%,表明只有一个线程可以在时间运行。

所以这是可能的,任何GDI +叫你从GUI线程做而定标过程中,将阻塞,直到规模完成。

0

我怀疑是因为缩放使用的是所有的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

我以某种方式怀疑是这种情况。我认为最可能的调用是问题。 – 2009-04-30 20:09:36

+0

在创建并启动上述子例程的子程序中,我已将优先级设置为BelowNormal。如果我将优先级设置为最低,则没有区别。 – Ski 2009-04-30 20:12:32

+0

Ski请提供有关如何异步调用此方法的详细信息。这样我们就可以提供帮助! – 2009-04-30 20:14:40

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 

另类 - 使用异步模式。

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!

0

ImageScaled()如何将图像浸回到UI?