我有一个基于vb.net的Windows应用程序,当点击"GO"按钮时,一堆数据被加载到DB中.所以在我的应用程序中,一旦单击"GO"按钮,我想要禁用它,并希望在上传完成后启用它.现在我的btnGo_Click()的具体方法我有:
btnGo.Enabled = False
Run Code Online (Sandbox Code Playgroud)
作为第一线和
btnGo.Enabled = True
Run Code Online (Sandbox Code Playgroud)
作为同一方法的最后一行.
但我不明白为什么"GO"虽然显示为禁用,但仍然允许在处理过程中点击.此外,如果我删除最后一行,它将永久禁用,并且不允许click事件.
请建议我做错了什么?
编辑(日期:2012年1月25日):我根据同事的建议进行了更改,但我在这里面临一个新问题.我面临的问题是文本框得到更新但并非总是如此.我已经在后台工作线程的"_ProgressChanged"事件中更新了我的文本框.在我的情况下,如果上传了10条记录.然后在texbox中有10行更新.但文本框中只显示了几行.这是再次重演的问题吗?请建议......因为所有其他事情都按照你的建议完成
Cod*_*ray 16
你没有做错任何事.问题是在事件处理程序方法内部的代码完成执行之前,UI不会更新.然后,该按钮被禁用并立即以快速顺序启用.
这就解释了为什么如果你忘记在事件处理程序方法结束时重新启用按钮控件,它仍然被禁用 - 因为你告诉它在方法的第一行中禁用按钮.
这是一个典型的例子,说明为什么你永远不应该在事件处理程序方法中执行长时间运行的计算任务,因为它阻止了UI的更新.计算实际上需要在单独的线程上进行.但是不要尝试手动创建线程,并且绝对不要尝试从单独的线程更新UI.而是使用该BackgroundWorker组件自动处理所有这些.链接的MSDN文档提供了有关如何使用它的绝佳示例.
在启动之前禁用该按钮BackgroundWorker,然后在其Completed事件中重新启用它,表示数据库负载已完成.
由于您尝试执行一个可能需要一些时间的函数,因此我建议您使用线程。在.NET 中有一个BackgroundWorker组件,它非常适合异步执行任务。
单击按钮时,像这样调用BackgroundWorker:
if not bgwWorker.IsBusy then
btnGo.enabled = false
bgwWorker.RunWorkerAsync()
end if
Run Code Online (Sandbox Code Playgroud)
并使用完成的事件再次启用按钮:
Private Sub bgwWorker_DoWork(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles bgwWorker.DoWork
' Do your things
End Sub
Private Sub bgwWorker_RunWorkerCompleted(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles bgwWorker.RunWorkerCompleted
' Called when the BackgroundWorker is completed.
btnGo.enabled = true
End Sub
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,我使用 bgwWorker 作为 BackgroundWorker 的实例。