wpf 立即从UI线程更新绑定属性

nwwlzxa7  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(224)

我看到的大多数问题都在问相反的问题--如何从非UI线程或后台线程更新UI。
在我的例子中,我想要的正好相反。在UI线程上运行的命令中,我可以调用或执行什么来表示Update the UI now吗?我认为这将类似于DoEvents过去的情况。尽量让这个问题保持一点通用性,以便它有希望在某个时候帮助其他人。
"我尝试过的事..."
我已经简化了我的命令函数,只是为了看看我是否可以让ProgressText更新工作。这些都不起作用。在整个函数执行后,只有最后一个文本显示,这是Progress Update 5。我想看到它依次通过每个更新文本。

Private Sub MoveOrRenameSongs()

    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 1"
    Application.Current.MainWindow.UpdateLayout()
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 2"
    Application.Current.MainWindow.UpdateLayout()
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 3"
    Application.Current.MainWindow.UpdateLayout()
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 4"
    Application.Current.MainWindow.UpdateLayout()
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 5"
    Application.Current.MainWindow.UpdateLayout()

    Dim myWindow As MainWindow = Application.Current.MainWindow
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 1"
    myWindow.UpdateLayout()
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 2"
    myWindow.UpdateLayout()
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 3"
    myWindow.UpdateLayout()
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 4"
    myWindow.UpdateLayout()
    System.Threading.Thread.Sleep(2000)
    ProgressText = "Progress update 5"
    myWindow.UpdateLayout()
End Sub
    • 更多背景和详细信息...**

我有一个命令,可以运行更长的时间,我想更新一些进度文本,因为它的进展。但是,因为命令函数是在UI线程中运行,它阻塞了UI,在UI中的进度文本不能更新。我明白了。
ProgressText绑定到dependency属性,该属性在其他即时运行的命令函数中工作正常。
x一个一个一个一个x一个一个二个x
我试过把处理放到一个后台线程中,但是后来我遇到了其他的问题。我将在这里列出一些,但是它们都是题外话。

  • 我可以调用Dispatcher. Invoke来更新ProgressText,但是
  • 我无法再打开需要收集一些输入的窗口;线程必须是STA
  • 我知道了如何使线程STA,但是我不能访问父线程来设置输入窗口的位置
  • 我克服了所有这些问题,当我在最后更新绑定列表时,它不再在UI中更新,因为代码都是为在UI线程上编写的,所以这些更新不起作用

因此,我想继续探索UI线程。这是一个个人应用程序,我把它作为一个爱好来编写。我不在乎UI是否会被锁定一段时间,但我想看到它工作的进度。

    • 最后成功的方法**

5个进度文本中的每一个都按预期连续出现。

Private Async Function MoveOrRenameSongs() As System.Threading.Tasks.Task
    System.Threading.Thread.Sleep(1000)
    ProgressText = "Progress update 1"
    Await System.Threading.Tasks.Task.Delay(100)
    System.Threading.Thread.Sleep(1000)
    ProgressText = "Progress update 2"
    Await System.Threading.Tasks.Task.Delay(100)
    System.Threading.Thread.Sleep(1000)
    ProgressText = "Progress update 3"
    Await System.Threading.Tasks.Task.Delay(100)
    System.Threading.Thread.Sleep(1000)
    ProgressText = "Progress update 4"
    Await System.Threading.Tasks.Task.Delay(100)
    System.Threading.Thread.Sleep(1000)
    ProgressText = "Progress update 5"
    Await System.Threading.Tasks.Task.Delay(100)
End Function
t98cgbkg

t98cgbkg1#

你可以简单地释放ui线程,给予它一些时间去做一些事情。
让你的命令异步。到底有多容易取决于你如何做你的命令。
使用community mvvm工具包,您可以创建一个带有异步任务的relay命令:

[RelayCommand]
    private async Task SaveTransaction()
    {
        // Expensive code
        await Task.Delay(100);
        // Expensive code
    }

等待任务。delay编译成一个计时器,你的代码被分割,所以它会在100毫秒后继续。它会短暂地暂停,但不会像线程一样阻塞UI线程。sleep会。任何堆积在调度器队列中的东西都会开始处理。然后代码继续。
如果您没有这样的异步友好命令实现,您可以考虑:
https://johnthiriet.com/mvvm-going-async-with-async-command/

相关问题