从另一个 window BackgroundWorker vb.net WPF 更新 UI
Update UI from another window BackgroundWorker vb.net WPF
我正在做一个 wpf 项目...我过去遇到过类似的问题,但没有得到答案,这就是我再次提问的原因:)
我的 WPF 应用程序有 2 个 windows,一个用作启动画面,第二个只是一个基本的 window,带有 canvas.The 启动画面有一个 BackGroundWorker
.现在,我有这个代码:
Dim h2 as new Window2
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
现在,我的问题是如何在 Window1 的 backgroundworker
中使用这段代码?我试过了:
Dim method as Delegate
Private Sub BgWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles BgWorker.DoWork
If h2.Dispatcher.CheckAccess Then
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
Else
h2.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method)
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
End if
我想在这里澄清一些事情:
• 我从另一个 SO post 获得示例代码(我从 C# 转换而来)
• Dim method as Delegate
,我真的不知道如何使用委托函数
• 上面的代码 returns 有一些例外,例如 Parameter name:Method , Value can not be null
(我知道这是什么意思,但正如我所说,我不知道在这种情况下如何使用委托函数)
任何帮助将不胜感激
您正在使用的代码试图通过 Dispatcher.BeginInvoke()
调用 UI 线程。这是在线程中执行此操作的方法,而不是在 BackgroundWorker
中执行此操作的方法。在 BGW 中,您应该调用 ReportProgress()
method combined with subscribing to the ProgressChanged
event.
但是,对于您要尝试做的事情,这一点都不好...
对于初学者:您应该永远在后台线程中创建控件!所有与 UI(用户界面)相关的工作必须总是,总是,总是 在 UI 线程上完成仅.
其次: 尝试在后台线程中执行此操作并没有很好的理由。你现在这样做的方式不断更新 UI 线程,导致它无论如何都变为 lag/freeze。你可以做的是批量添加按钮,但正如我之前所说,你根本不应该在后台线程中创建控件。
最后: 迭代几个文件并为它们创建按钮的整个操作确实不是很繁重。除非你有数以千计的文件(在这种情况下,你应该只 显示 它们分批)这不会花那么长时间在 UI线程。
结论: 跳过 BackgroundWorker
和 运行 您在 UI 线程上的代码。如果你有大量的文件要加载,将它们的路径存储在一个列表中,只分批加载它们,让用户决定何时加载下一批文件。
我正在做一个 wpf 项目...我过去遇到过类似的问题,但没有得到答案,这就是我再次提问的原因:)
我的 WPF 应用程序有 2 个 windows,一个用作启动画面,第二个只是一个基本的 window,带有 canvas.The 启动画面有一个 BackGroundWorker
.现在,我有这个代码:
Dim h2 as new Window2
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
现在,我的问题是如何在 Window1 的 backgroundworker
中使用这段代码?我试过了:
Dim method as Delegate
Private Sub BgWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles BgWorker.DoWork
If h2.Dispatcher.CheckAccess Then
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
Else
h2.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method)
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
End if
我想在这里澄清一些事情:
• 我从另一个 SO post 获得示例代码(我从 C# 转换而来)
• Dim method as Delegate
,我真的不知道如何使用委托函数
• 上面的代码 returns 有一些例外,例如 Parameter name:Method , Value can not be null
(我知道这是什么意思,但正如我所说,我不知道在这种情况下如何使用委托函数)
任何帮助将不胜感激
您正在使用的代码试图通过 Dispatcher.BeginInvoke()
调用 UI 线程。这是在线程中执行此操作的方法,而不是在 BackgroundWorker
中执行此操作的方法。在 BGW 中,您应该调用 ReportProgress()
method combined with subscribing to the ProgressChanged
event.
但是,对于您要尝试做的事情,这一点都不好...
对于初学者:您应该永远在后台线程中创建控件!所有与 UI(用户界面)相关的工作必须总是,总是,总是 在 UI 线程上完成仅.
其次: 尝试在后台线程中执行此操作并没有很好的理由。你现在这样做的方式不断更新 UI 线程,导致它无论如何都变为 lag/freeze。你可以做的是批量添加按钮,但正如我之前所说,你根本不应该在后台线程中创建控件。
最后: 迭代几个文件并为它们创建按钮的整个操作确实不是很繁重。除非你有数以千计的文件(在这种情况下,你应该只 显示 它们分批)这不会花那么长时间在 UI线程。
结论: 跳过 BackgroundWorker
和 运行 您在 UI 线程上的代码。如果你有大量的文件要加载,将它们的路径存储在一个列表中,只分批加载它们,让用户决定何时加载下一批文件。