首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否同步更新用户界面?

是否同步更新用户界面?
EN

Stack Overflow用户
提问于 2011-11-03 20:12:30
回答 3查看 718关注 0票数 4

考虑这个例子:

代码语言:javascript
运行
复制
Private Sub Button_Click(
    sender As Button, e As RoutedEventArgs) Handles btn.Click

  sender.IsEnabled = False

  Thread.Sleep(5000)

  sender.IsEnabled = True
End Sub

在我的场景中,Button_Click是VM中的命令代理,而Thread.Sleep是一些长时间运行的进程(大约2-10秒)。

我希望,当用户调用命令时,它应该立即更新禁用按钮的UI,以便用户在运行时无法执行该按钮,然后执行该操作,然后,当操作完成时,取消阻止该按钮。

我试着像下面这样换行:

代码语言:javascript
运行
复制
Dispatcher.BeginInvoke(Sub() Thread.Sleep(5000))

但它并没有起到作用。

做这件事最好的方法是什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-11-03 22:05:33

您也可以使用BackgroundWorker控件,而不是创建自己的线程。通过调用"RunWorkerAsync“方法,在另一个线程中调用了DoWork事件get。

通过从你的UI线程调用"CancelAsync“方法,你可以将后台工作者设置为”取消挂起“(控件"CancellationPending”的属性为true)。在长时间运行的后台线程中,你可以检查这个属性(例如,如果你有一个循环:只要CancellationPending为真就退出循环)。这是一个非常好的特性,可以安全地中止线程。

此外,使用后台工作者,您还可以报告线程的进度(例如,在ProgressBar中使用)

示例:

代码语言:javascript
运行
复制
Public Class Form1

   Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load

      '** Set to true if you want the ReportProgress Event
      BackgroundWorker1.WorkerReportsProgress = True
      BackgroundWorker1.WorkerSupportsCancellation = True
   End Sub

   Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

      Dim i As Integer
      Dim n As Integer = 100
      Dim iLastPerc As Integer


      While Not BackgroundWorker1.CancellationPending AndAlso i < n

         '** Do your time consuming actions here
         Threading.Thread.Sleep(500)

         If Math.Floor((i / n) * 100) > iLastPerc Then
            '** If the Progress has changed. Report
            iLastPerc = CInt(Math.Floor((i / n) * 100))
            BackgroundWorker1.ReportProgress(iLastPerc)
         End If

         i += 1
      End While

   End Sub

   Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click

      '** Run the Backgroundworker
      BackgroundWorker1.RunWorkerAsync()

   End Sub

   Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged

      '** Update the ProgressBar
      ProgressBar1.Value = e.ProgressPercentage

   End Sub

   Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted

      '** Worker is done. Check for Exceptions or evaluate the Result Object if you like

   End Sub

   Private Sub btnCancel_Click(sender As System.Object, e As System.EventArgs) Handles btnCancel.Click

      '** Cancel the worker
      BackgroundWorker1.CancelAsync()

      MsgBox("Finished!")

   End Sub
End Class

关于你的问题,代码应该是:

代码语言:javascript
运行
复制
Private Sub btn_Click(sender As Button, e As RoutedEventArgs) Handles btn.Click
  sender.IsEnabled = False
  Using bw As New BackgroundWorker()
    AddHandler bw.DoWork, Sub(s, ea) Thread.Sleep(5000)
    AddHandler bw.RunWorkerCompleted, Sub(s, ea) sender.IsEnabled = True
    bw.RunWorkerAsync()
  End Using
End Sub
票数 1
EN

Stack Overflow用户

发布于 2011-11-03 20:59:00

按钮单击事件是由UI线程处理的,因此当您调用thread.sleep时,您将使UI线程休眠,并且在方法结束之前看不到任何更改。

因此,您需要在新线程上运行该进程,并且当该进程结束时,使用dispatcher更改UI。

例如:

代码语言:javascript
运行
复制
Private event TaskEnded()
Private Sub Button_Click(sender As Button, e As RoutedEventArgs) Handles btn.Click
  btn.IsEnabled = False
  dim l as new Thread(sub()
                       Thread.Sleep(5000)
                       RaiseEvent TaskEnded
                       End Sub)
  l.start()
End Sub

Private Sub bla() Handles Me.TaskEnded
  dispatcher.BeginInvoke(sub()
                           btn.IsEnabled = True
                         end sub)
End Sub

使用MVVM的方式,您将把按钮的IsEnabled属性绑定到viewModel中的布尔值属性,然后直接在按钮上更新VM属性。

票数 2
EN

Stack Overflow用户

发布于 2011-11-03 20:34:37

将button enabled属性绑定到VM中的属性(比如ProcessComplete)。

使用onclick事件按钮来触发VM中的一个方法,该方法启动冗长的进程。在进程运行时保持ProcessComplete为假,然后在进程完成时将其设置为真。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7994638

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档