Winforms ProgressBar 需要时间来渲染
我在使用 PorgressBar 时注意到了这一点。如果我将值设置为 x,则显示的值不会立即更新,需要花费少量时间来绘制它,因为条形图从当前值动画到新值。
在以下代码中很容易看出这一点:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Label1.Text = ""
Dim progressHandler = New Progress(Of Integer)(Sub(value) ProgressBar1.Value = value)
Dim progress = CType(progressHandler, IProgress(Of Integer))
Await Task.Run(Sub()
For i = 1 To 100
progress.Report(i)
Thread.Sleep(10)
Next
End Sub)
Label1.Text = "Value Now at 100%"
Await Task.Delay(650) 'it takes this long for the bar to be rendered
Label1.Text += " - Finished drawing"
End Sub
您会注意到运行此代码时,Value Now at 100%
出现在条形实际达到 100% 之前很长时间。
有什么方法可以检测栏何时完成渲染?
I have noticied that when using the PorgressBar. If I set the value to x, the value displayed is not immediately updated, it takes a small amount of time to draw it as the bar is animated from its current value to the new value.
This is easy to see in the following code:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Label1.Text = ""
Dim progressHandler = New Progress(Of Integer)(Sub(value) ProgressBar1.Value = value)
Dim progress = CType(progressHandler, IProgress(Of Integer))
Await Task.Run(Sub()
For i = 1 To 100
progress.Report(i)
Thread.Sleep(10)
Next
End Sub)
Label1.Text = "Value Now at 100%"
Await Task.Delay(650) 'it takes this long for the bar to be rendered
Label1.Text += " - Finished drawing"
End Sub
You will notice running this code that the Value Now at 100%
appears a long time before the bar has actually reached 100%.
Is there any way that I can detect when the bar has finished rendering?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我刚刚尝试了一下,完全明白你的意思。不幸的是,在花了一些时间查看进度栏上的 DrawToBitmap 函数是否有帮助之后,我发现了不足。
下一步是创建一个自定义进度条,用于公开渲染完成时的事件。
有关如何创建自定义进度条的合理示例,请尝试此处:
http://msdn。 microsoft.com/en-us/library/system.windows.forms.progressbarrenderer(v=VS.100).aspx
快速扫描代码看起来您应该能够插入“OnRendered”事件或类似的调用“DrawHorizontalChunks”(或“DrawVerticalChunks”)。
可能不是您想要的答案,但至少为您提供了追求它时所需的控制权?
注意:我自己还没有尝试过,所以如果您花了一整天的时间发现得到了相同的结果,请不要向我发送仇恨邮件...
祝您好运!
编辑:
对我的回复不满意,似乎有点懒......下面使用我所描述的自定义进度栏。它有几个基本属性,用于设置最大/最小值、执行步骤以及直接设置值。我通过将睡眠间隔更改为不同的量来对此进行了测试,在所有情况下,表单在关闭之前都将进度条显示为已满。请注意新的 OnRendered 事件。
I just tried this out and can see exactly what you mean. Unfortunately after spending a little while seeing if the DrawToBitmap functions on the progress bar might help, I've come up short.
The next step would be to create a custom progress bar that exposes events for when rendering has completed.
For a reasonable example on how to create a custom progress bar, try here:
http://msdn.microsoft.com/en-us/library/system.windows.forms.progressbarrenderer(v=VS.100).aspx
A quick scan over the code looks like you should be able to plug in an 'OnRendered' event or similar on or around the calls to 'DrawHorizontalChunks' (or 'DrawVerticalChunks').
Probably not the answer you was after, but at least gives you the control you need if you pursue it?
Note: I haven't tried this myself, so please don't send me hate mail if you spend all day on this to find you get the same results...
Good Luck!
EDIT:
Wasn't happy with my response, seemed a bit lazy... The following uses a custom progress bar as I described. It has a couple basic properties for setting Max/Min values, Performing steps, and setting the value directly. I've tested this by changing the sleep interval to various amounts, in all cases the form displayed the progress bar as full before closing. Note the new OnRendered event.
问题是您处于单线程程序中,并且线程需要时间来更新显示。
添加行
Before close the
UpdateProgress
sub.并且您可以摆脱最后两次刷新。
The problem is that you're in a single threaded program and the thread needs time to update the display.
Add the line
Before closing the
UpdateProgress
sub.And you can get rid of the last two refresh.
这是我根据 Matt Wilko 的建议编写的代码:
This is my code based on Matt Wilko's suggestion:
我的进度条滞后效果很好,使用此函数设置值:
更多信息:
https://derekwill.com/2014/06/24/combating-the-lag-of-the-winforms-progressbar/
I have good results with progressbar lag, setting the value with this function:
More information:
https://derekwill.com/2014/06/24/combating-the-lag-of-the-winforms-progressbar/
我有类似的问题。
我更愿意起诉标准进度条,以便在应用程序中拥有典型的设计。
确实,它需要时间来更新,并且由于 DoEvents 本身无法工作,因此我建议使用后台工作者来进行加载。当完成后仍然不起作用,那么要么添加一个doevents,要么一个小的延迟。但我想您的解决方案延迟 100 毫秒是最好的,因为它需要的更改最少并且仍然有效。只添加 10 毫秒的延迟怎么样?
另一种方法是:尝试progressBar.Invalidate(强制重新绘制),添加代码来绘制,检查绘制是否被执行,然后关闭表单。我猜 DoEvents 在绘画中不起作用,因为绘画需要完成。所以你可以启用一个间隔为 100 毫秒的计时器,它会关闭窗口。
关于 1/24 秒以内的一切对于人类来说是看不见的都是 bu..sh..
眼睛里有液体,甚至可以看到更短的东西。如果我们能够立即对某件事做出反应,那是有区别的,但由于信息被“燃烧”在眼睛表面,直到被神经“读取”,所以它不会丢失。甚至60Hz也存在问题,我相信大多数人都知道恼人的60Hz CRT问题。 LCD 闪烁不会那么强烈,但如果您需要高帧率,而 60 还不够,那么您仍然可以“看到”60 的问题,并且 100 或更高看起来更好。
I have a similar problem.
I would prefer to sue the standard progress bar in order to have a typical design in the application.
It is true that it needs time to update, and since DoEvents does not work on its own, I would recommend to do the loading by using a backgroundworker. When finished and it still doesn't work, then either add a doevents, or a small delay. But I guess your solution to ad a delay of 100ms would be best, since it requirest the fewest changes and is still working. what about just adding 10ms delay to it.
The other way would be: try progressBar.Invalidate (force a repaint), add code to paint, which checks if paint is executed, and then close the form. I guess DoEvents won't work in paint, since paint needs to finish. so you could enabl a timer with 100ms interval and it would close the window.
about everything less 1/24s is invisible for humans is bu..sh..
there are liquids in the eye which see even mcuh shorter things. It is a difference if we can immediately react to something, but since the information is 'burned' on the surface of the eyes until it will be 'read' by nerves, it is not lost. there are even problems with 60Hz, and I am sure most people know that annoying 60Hz crt problem. LCD does not flicker that intense, but if you need a high framerate, and 60 is not enough, then you can still 'see' the problems with 60 and it looks mcuh better with 100 or higher.
我发现使用 PerformStep() 而不是设置值没有这种渲染延迟 - 但仍然必须调用 Application.DoEvents() 。
I found that using PerformStep() instead of setting the value did not have this rendering delay - still had to call Application.DoEvents() though.
我通过插入得到了可接受的结果
frmMain.Refresh
为标准 ProgressBar 分配新值后。
I got an acceptable result by inserting
frmMain.Refresh
after assigning a new value to the standard ProgressBar.