从另一个线程更新UI使应用程序运行非常慢 [英] Update the UI from another thread makes the app runs very slow

查看:87
本文介绍了从另一个线程更新UI使应用程序运行非常慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,可以逐字节读取二进制文件,并在ProgressBar中报告读取进度.

我使用BackgroundWorker在另一个线程中读取了文件,并使用ReportProgres更新了UI.

我的问题是,由于ReportProgres,应用程序运行非常缓慢.对于10 MB的文件,大约需要3分钟,如果我对ReportProgress行进行注释,则需要2秒.

有什么想法吗?

I have an application that reads binary files byte by byte and report reading progress in a ProgressBar.

I read the file in another thread using a BackgroundWorker and I update the UI using ReportProgres.

My problem is that the application runs very slow because of ReportProgres. For a 10 MB file takes about 3 minutes, if I comment the ReportProgress line, takes 2 seconds.

Any ideas about this?

推荐答案

如果在处理的每个字节上更新ProgressBar,则确实会非常慢.在某种程度上,对UI元素的调用非常昂贵,这在非常频繁调用时会变得非常明显(也因为调用需要在用户线程中调用).一种简单的方法是检查是否实际上有任何重大进度要报告,然后才进行报告.您可以为此使用各种高级方案,但是为了进行测试,只需使用类似以下内容的方法:
If you update the ProgressBar on every byte handled then it will indeed be very slow. Calls to UI elements are very expensive to a certain degree which will become very noticeable when called very often (also because the call needs to be invoked into the user thread). A simple way is to check if there is actually any significant progress to report and only then report it. You can use all kind off advanced schemes for this but for the sake of testing, simply use something like:
If((current_byte_handled And 127) = 127) Then
  ReportProgres ...
End If



这将限制呼叫数量,并且应该已经使其更快.

祝你好运!



This will limit the number of calls and should make it faster already.

Good luck!


我们真的需要回答吗?

如果尝试逐字节发送通知,则将执行10,485,760次调用.与一次调用相比,读取一个字节不花时间.调用使用参数将其调用所需的所有数据打包到委托实例中,将该数据包在UI线程调用队列中排队,然后返回(如果是BeginInvoke),或者等待直到UI线程从队列中删除此包,使用UI控件执行实际的调用,处理事件并通知调用Invoke的线程.与读取字节相比,您是否要测量此类通知的开销?也许您已经可以估计它了.

那么,每个字节上的通知有意义吗?想一想.

有关调用的更多详细信息,请参见我过去的回答:
Control.Invoke()与Control.BeginInvoke() [ ^ ],
Treeview Scanner和MD5问题 [
Do we really need to answer?

If you try to send notification byte-by-byte, you perform 10,485,760 invocations. Reading of one byte takes no time compared to one invocation. The invocation packs the delegate instance with all the data required to its call with parameters, queues this packet in the UI thread invocation queue and either returns (in case of BeginInvoke) or waits until the UI thread remove this package from the queue, performs the actual call using UI controls, processes events and notifies the thread calling Invoke. Do you want to measure the overhead of such notification compared to reading a byte? Perhaps you already can estimate it.

So, does the notification on each byte make any sense? Just think about it.

For more detail on invocation, please see my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

—SA


这篇关于从另一个线程更新UI使应用程序运行非常慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆