c# – 在WPF中创建繁重的用户控件

我知道我不能生成不同的线程并将其放在UI线程中以将其添加到Visual Tree中,因为它会抛出一个异常,它无法访问该对象,因为另一个线程拥有它.

我目前的情况是我正在大量创建UI控件运行时,比如200(FrameworkContentElement)控件并将其添加到DockWindow.我是否有可能在创建它时不冻结UI并尝试将它们加载到UI线程?我甚至无法显示进度对话框,因为当在另一个线程上工作时显示对话框时会使用UI线程,如果我需要处理的是数据并将其放在UI中,这是好的,但这次我需要创建这些UI控件.

我认为的一种方法是创建UI控件并将它们序列化为MemoryStream并将它们加载到UI线程,这里的一个问题是我必须将DataContext重新附加到控件但是那很好,那一刻我可以将它委托给另一个线程.问题还在于这是可行的吗?

我尝试混合Task和Thread对象使ApartmentState成为STA但仍然没有运气.

public static Task<T> StartSTATask<T>(Func<T> func)
    {
        var tcs = new TaskCompletionSource<T>();
        Thread thread = new Thread(() =>
        {
            try
            {
                tcs.SetResult(func());
            }
            catch (Exception e)
            {
                tcs.SetException(e);
            }
        });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        return tcs.Task;
    }

编辑:这些控件再次是FrameworkContentElement,在这种情况下虚拟化控件将无济于事.这是使用FlowDocument控件在运行时创建控件.说,运行,表,段落等.因此,ListBox,TreeViews等不适用于此场景.

最佳答案 200个控件不应该构成一个很大的问题,在一个体面的机器上呈现WPF可能需要几千个原语.

您可以在加载数据时和解析数据时显示进度条.然后,如果需要,可以通过对数据进行u-UI线程进程循环并调用UI线程来实例化控件来限制创建UI元素.你甚至可以通过一个小的睡眠来分隔实例,让屏幕渲染,但只能用于非常繁重的UI ……

…说的是 – 如果你的用户界面太重,你可能错误地设计了它.问题不应该是
 “在我的UI减速到拖动之前,我可以放多少个UI元素?”
   但
 “可以完成这项工作的活动UI元素的最小数量是多少?”

“活动”一词指的是列表视图所采用的方法,其中实际项目是虚拟化的 – 它们仅在需要时创建并在不可见时处理.因此,如果你的用户界面允许,可以考虑使用一个虚拟化容器(如ListView)而不是DockPanel.

如果您可以提供特定UI元素的示例,我可以进一步详细说明.

点赞