我为我的老板创建了一个图像查看控件,它包含平移,通过鼠标滚轮缩放,以及绘制一个缩放的框。控件需要支持非常大的图像文件(即每侧数千个像素)。
一切正常,但只要代码缩放图像,控件UI就会无法响应。我的老板让我使用线程将缩放代码设置为与UI分开。扩展代码现在肯定是在一个单独的线程上,但在扩展代码运行时UI仍然陷入困境!谁能帮帮我呢?
以下是缩放代码。如果这还不足以帮助我,请告诉我,我会发布您需要的任何代码!
更新:这是完整的控制代码。 link text
答案 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 +调用都可能会阻塞,直到缩放完成为止。