在我的应用程序中,我调用了一个更新软件的过程 - 它存储在自己的类中.即使您Application.DoEvents()出于某种原因在少数几个地方写作,更新表单中的标签也没有更新,表单本身也处于非活动状态.
Namespace software
Public Class updater
Public Function UpdateSoftware(ByVal url As String, ByVal downloadFolder As String) As Boolean
Application.DoEvents()
Thread.Sleep(1000)
frmUpdate.lblResult.Text = "Update is about to begin"
Thread.Sleep(1000)
frmUpdate.lblResult.Text = "Downloading data"
Thread.Sleep(1000)
Application.DoEvents()
frmUpdate.lblResult.Text = "About to start the writing process"
Application.DoEvents()
frmUpdate.lblResult.Text = "Software was updated, please restart your device."
End Function
End Class
End Namespace
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚你DoEvents在这些特定地点打电话的原因,因为它们都没有任何明显的效果.第一个发生在任何标签更改之前,因此允许表单刷新是没有意义的.在完成所有长期工作(三次睡眠)之后,其他人都处于最后阶段.因此,虽然他们将允许表单在执行离开方法之前刷新,但它很快就会离开方法,所以在那里也没有意义.唯一的地方,它甚至将适用于呼叫DoEvents会之间两项长时间运行的东西.例如,如果你这样做,你会注意到一个区别:
Public Function UpdateSoftware(ByVal url As String, ByVal downloadFolder As String) As Boolean
Thread.Sleep(1000)
frmUpdate.lblResult.Text = "Update is about to begin"
Application.DoEvents()
Thread.Sleep(1000)
frmUpdate.lblResult.Text = "Downloading data"
Application.DoEvents()
Thread.Sleep(1000)
frmUpdate.lblResult.Text = "About to start the writing process"
frmUpdate.lblResult.Text = "Software was updated, please restart your device."
End Function
Run Code Online (Sandbox Code Playgroud)
您需要了解,在.NET WinForms(以及WPF)中,UI在单个线程上运行.我的意思是,如果你的一个事件处理程序包含需要很长时间才能完成的代码,那么UI将在事件处理程序执行的整个时间内被冻结.UI刷新完全被阻止,直到最后一个事件处理程序完成它正在做的任何事情. DoEvents在某种程度上是一种破解方式(以及危险的黑客攻击).每次调用时DoEvents,它都会将控制权返回给表单,以处理排队等待的其他内容(例如重新绘制屏幕并处理用户输入),然后执行返回到原始事件处理程序,以便它可以继续执行关闭.这意味着,每次调用时DoEvents,它都允许表单在该点重新绘制,但事件处理程序仍然阻止所有的UI之间的UI DoEvents.
正如其他人已经暗示的那样,使用DoEvents非常气馁.它不仅不太有效,而且可能导致各种意外行为.在.NET的早期版本(例如VB6)中,DoEvents通常是唯一的选择,但在.NET中,多线程相对容易.在某些情况下DoEvents,合法地仍然有用,但它们应该是非常少而且很少,并且只有非常谨慎和谨慎地实施.
在WinForm应用程序中有两种推荐的实现多线程的方法.原始方法仍然有效,是使用一个BackgroundWorker组件(你可以在WinForm设计器工具箱中找到它).在BackgroundWorker提出不同的线程上的事件,这样就可以把你所有的长时间运行工作,该事件处理程序,如果没有它阻塞UI.然后,当它全部完成时,它会引发另一个事件,返回UI线程,以便您可以在工作完成后更新UI.
更新,更容易阅读但更复杂的方法是使用Async和Await关键字来制作所有长时间运行的方法,以及调用它们的事件处理程序,这是异步的.