.net 是否可以在一个单独的线程中创建可以返回到UI线程使用的控件?

.net 是否可以在一个单独的线程中创建可以返回到UI线程使用的控件?,.net,wpf,vb.net,multithreading,.net,Wpf,Vb.net,Multithreading,我的项目根据提供的XML文件的内容设置TabItems的内容。读取XML文件并将内容添加到TabItem中,其中可能包括文本块、边框、按钮、OxyPlot等 这可能需要相当长的时间,具体取决于XML文件的大小和复杂性。最理想的情况是,我希望在一个单独的线程中构建TabItem的内容,然后将其返回到UI线程以显示 问题是创建控件的线程拥有它们,我无法在UI线程上使用它们 有没有办法更改控件的线程所有权?欢迎使用SO 控件本身需要在主线程上创建,但您始终可以控制它们在单独线程(或者更确切地说,任务)

我的项目根据提供的XML文件的内容设置TabItems的内容。读取XML文件并将内容添加到TabItem中,其中可能包括文本块、边框、按钮、OxyPlot等

这可能需要相当长的时间,具体取决于XML文件的大小和复杂性。最理想的情况是,我希望在一个单独的线程中构建TabItem的内容,然后将其返回到UI线程以显示

问题是创建控件的线程拥有它们,我无法在UI线程上使用它们

有没有办法更改控件的线程所有权?

欢迎使用SO

控件本身需要在主线程上创建,但您始终可以控制它们在单独线程(或者更确切地说,任务)中创建的速率。下面是一个视图模型,它以故意减慢的速度创建颜色:

public class MainViewModel : ViewModelBase
{
    public ObservableCollection<Color> Colors { get; } = new ObservableCollection<Color>();

    public MainViewModel()
    {
        Task.Run(async () =>
        {
            foreach (var color in ColorStructToList())
            {
                await Task.Delay(TimeSpan.FromMilliseconds(10));
                Application.Current.Dispatcher.Invoke(() => this.Colors.Add(color));
            }
        });

    }

    // courtesy https://stackoverflow.com/a/16130999/1177147
    public static List<Color> ColorStructToList()
    {
        return typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
                            .Select(c => (Color)c.GetValue(null, null))
                            .ToList();
    }

}
public类MainViewModel:ViewModelBase
{
公共ObservableCollection颜色{get;}=new ObservableCollection();
公共主视图模型()
{
Task.Run(异步()=>
{
foreach(ColorStructList()中的var color)
{
等待任务延迟(时间跨度从毫秒(10));
Application.Current.Dispatcher.Invoke(()=>this.Colors.Add(color));
}
});
}
//礼貌https://stackoverflow.com/a/16130999/1177147
公共静态列表ColorStructList()
{
返回typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
.Select(c=>(颜色)c.GetValue(null,null))
.ToList();
}
}
这里有一个ItemsControl,它将创建项目以在创建时显示这些项目,而不占用GUI主线程:

<ItemsControl ItemsSource="{Binding Colors}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Width="10" Height="10" Margin="2" >
                <Rectangle.Fill>
                    <SolidColorBrush Color="{Binding}" />
                </Rectangle.Fill>
            </Rectangle>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

你不能。当处于冻结状态时,线程之间只能传递
Freezable
类型。通用控件不是从
Freezable
派生的。您可以异步处理XML文件,并在适用时使用数据虚拟化。像
ListView
这样的控件也提供了UI虚拟化。通常,数据处理可以移动到后台线程,但UI属于UI线程。