“调用线程必须是 STA,因为许多 UI 组件都需要这个”,使用 BeginInvoke 动态添加列表视图项时

本文关键字:BeginInvoke 使用 动态 视图 列表 添加 线程 调用 STA 因为 组件 | 更新日期: 2023-09-27 18:09:13

我正在尝试从BackgroundWorker调用一个将用户控件添加到ListView的方法:

private void AddItems(List<FileItem> fileItems) {
    System.Threading.Thread.CurrentThread.SetApartmentState(System.Threading.ApartmentState.STA);
    Dispatcher.BeginInvoke(new Action(() => files.ItemsSource = fileItems));
}

用户控件files在其构造函数中成功从fileItems获取数据,但它会引发The calling thread must be STA, because many UI components require this.异常。我已经尝试将[STAThread]属性一一添加到所有父方法,但它仍然抛出异常。我应该在哪里添加此属性?

更新

另请注意,Dispatcher.BeginInvoke(new Action(() => files.Items.Clear()));正在正确执行。

“调用线程必须是 STA,因为许多 UI 组件都需要这个”,使用 BeginInvoke 动态添加列表视图项时

Dispatcher是指与 BGW 线程关联的线程,而不是 WPF/UI 线程。默认情况下,如果没有与当前线程关联,则将创建新的调度程序/上下文;在上下文中,这是完全没有用的。

如果从启动 BGW 的 UI 线程提供调度程序实例 (Dispatcher.CurrentInstance(,那么它"应该可以工作"。同样,正如 Hans 指出的那样,正确的 (WPF/UI( 调度程序对象应该可以通过与应用程序关联的调度程序进行访问。

此外,可以在 ReportProgress 方法中提供任意对象;这允许将信息发送回父对象。然后,可以在事件处理程序中完成 UI 组件的处理,该处理程序在正确的 WPF/UI 线程上自动运行。(这同样适用于"工作完成"处理。

无需为标准 WPF 项目设置任何 STA 线程选项/属性。

直接

在列表视图控件上调用 BiginInvoke,如下所示:

files.BeginInvoke(new Action(() => files.ItemsSource = fileItems));