防止Windows窗体上的UI冻结. [英] Preventing UI freeze on windows form.
问题描述
大家好,
我正在编写一个小型桌面应用程序,该应用程序会调整图像大小以便在线发布,并且在执行计算以确定要处理图像的合并转换文件大小时遇到界面冻结的小问题.
只要使用计时器和后台工作人员更改应用程序上的轨迹栏,我就会执行计算.
然后,背景工作人员执行计算并以线程安全的方式更改表单上标签的值.
然后在bwCalculator_RunWorkerCompleted
例程中将布尔runFileSizeCalculation
重置为true.
尽管工作人员正在执行此操作,但我的界面死机了.后台工作人员的目的不是阻止这一点吗?
我是桌面编程的新手,所以要保持柔和.我通常是Web开发人员,我只是觉得这会很有趣,也许以后我可以分享一些有用的信息.
提前非常感谢.
好吧...首先,谢谢里克和约翰提供的信息.
我已经在使用invoke来允许更新标签,并且我对其他信息有所了解.这是我一起扔的东西.
Private Sub tbRatio_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbRatio.ValueChanged lblRatio.Text = String.Format("{0}%", tbRatio.Value) reductionRatio = tbRatio.Value If filteredList IsNot Nothing Then If runFileSizeCalculation Then runFileSizeCalculation = False Dim t As New Thread(AddressOf ThreadingTest) t.Start() End If End If End Sub Private Sub ThreadingTest() Dim dueTimeSpan As New TimeSpan(0, 0, 3) latencyTimer = New Threading.Timer(AddressOf SetOutputFolderSize, Nothing, dueTimeSpan, infiniteTimeSpan) End Sub Delegate Sub SetOutputFolderSizeCallback() Private Sub SetOutputFolderSize() If lblOutputSize.InvokeRequired Then Dim d As New SetOutputFolderSizeCallback(AddressOf SetOutputFolderSize) Invoke(d) Else lblOutputSize.Text = (String.Format("{0} MB", GetOutPutFolderSize(filteredList).ToString)) runFileSizeCalculation = True End If End Sub
GetOutPutFolderSize
函数是执行实际计算的函数.
我仍然遇到同样的冻结问题....我缺少明显的东西吗?
再次感谢.
****************************************************** *********************
再次感谢Rick,您的工作更加明智,并且已停止UI冻结.
使用计时器的原因是要在设置的延迟后运行该函数,以便在更改轨迹栏值的时间少于在计算文件夹大小所花费的时间中多次更改后,它希望仅捕获最后一个值并根据以下内容运行计算在那之上.
您能想到一种更好的方法吗?
我通常如何处理这种类型的问题是要么生成一个新的 ^ ]或使用ThreadPool.QueueUserWorkItem方法使用 ^ ]线程.线程主体将完成工作并异步结束.如果需要更改任何Form或其子控件UI属性,请确保在它们上调用Invoke().请参见此 [
[已更新,显示了使用延迟计时器]
随着Rick的响应,您还可以创建自定义事件,该事件可用于向订阅对象通知重要事件的进度.线程.我使用线程池和自定义事件,效果很好.我还要重申里克关于使用Invoke
允许事件处理程序更新UI的建议.
Hi all,
I''m writing a small desktop app that resizes images for posting online and i''ve hit a small problem with the interface freezing when I am performing a calculation to determine the combined converted filesize of images to be processed.
I''m performing the calculation whenever the trackbar on my app is changed with a timer and a backgroundworker.
The backgroundworker then performs the calculation and changes the value of a label on the form in a threadsafe manner.
The boolean runFileSizeCalculation
is then reset back to true in the bwCalculator_RunWorkerCompleted
routine.
Whilst the worker is doing it''s thing though, my interface freezes. Isn''t the purpose of the backgroundworker to stop this?
I''m new to desktop programming so be gentle. I''m a web developer normally I just thought this would be a bit of fun and maybe something useful I could share afterwards.
Many thanks in advance.
Ok ..... First, Thanks Rick and John for your info.
I was already using invoke to allow the update to the label and I''ve had a bit of a read of the other info. Here''s what I''ve thrown together.
Private Sub tbRatio_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbRatio.ValueChanged lblRatio.Text = String.Format("{0}%", tbRatio.Value) reductionRatio = tbRatio.Value If filteredList IsNot Nothing Then If runFileSizeCalculation Then runFileSizeCalculation = False Dim t As New Thread(AddressOf ThreadingTest) t.Start() End If End If End Sub Private Sub ThreadingTest() Dim dueTimeSpan As New TimeSpan(0, 0, 3) latencyTimer = New Threading.Timer(AddressOf SetOutputFolderSize, Nothing, dueTimeSpan, infiniteTimeSpan) End Sub Delegate Sub SetOutputFolderSizeCallback() Private Sub SetOutputFolderSize() If lblOutputSize.InvokeRequired Then Dim d As New SetOutputFolderSizeCallback(AddressOf SetOutputFolderSize) Invoke(d) Else lblOutputSize.Text = (String.Format("{0} MB", GetOutPutFolderSize(filteredList).ToString)) runFileSizeCalculation = True End If End Sub
The GetOutPutFolderSize
function is the one that performs the actual calculation.
I''m still getting the same freezing problem.... Am I missing something obvious?
Thanks again.
***********************************************************************
Thanks again Rick, your working was much more sensible and has stopped the UI freeze.
The reason for using the timer was to run the function after a set delay so that when you change the trackbar value more than once in less than the time it took to calculate the foldersize it would hopefully catch only the last value and run the calculation based upon that.
Can you think of a better way of doing that?
How I usually approach this type of problem is to either spawn a new thread[^] or use the ThreadPool.QueueUserWorkItem method to use a ThreadPool[^] thread. The body of the thread will do the work and end asynchronously. If you need to change any of the Form or its child controls UI properties, be sure to call Invoke() on them. See this [^] for guidance.
Your code is still executing the work on the UI thread. That''s why you have a pause.
KeepingtbRatio_ValueChanged
the same, try something like this(may need massaging):
Dim m_outputSize As String = String.Empty Private Sub ThreadingTest() Dim dueTimeSpan As New TimeSpan(0, 0, 3) latencyTimer = New Threading.Timer(AddressOf SetOutputFolderSize, Nothing, dueTimeSpan, infiniteTimeSpan) m_outputSize = GetOutPutFolderSize(filteredList).ToString() End Sub Private Sub SetOutputFolderSize() If lblOutputSize.InvokeRequired Then Dim d As New SetOutputFolderSizeCallback(AddressOf SetOutputFolderSize) Invoke(d) Else lblOutputSize.Text = (String.Format("{0} MB", m_outputSize)) runFileSizeCalculation = True End If End Sub
[Updated to show use of the latency timer]
Along with Rick''s response, you can also create custom events that you can use to notify subscribed objects of the progress of important events within the thread. I use a thread pool, and custom events and it works great. I also would like to reiterate Rick''s recommendation of the use of Invoke
to allow the event handlers to update the UI.
这篇关于防止Windows窗体上的UI冻结.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!