当前位置 : 主页 > 编程语言 > c语言 >

wpf – TaskFactory新UI创建

来源:互联网 收集:自由互联 发布时间:2021-06-24
如何使用TaskFactory创建新的UI元素?当我尝试时,我收到以下错误: 调用线程必须是STA,因为许多UI组件都需要这个. 示例代码 Dim txtBoxList as new List(Of TextBox)Sub StartThread() Dim TS As TaskSchedule
如何使用TaskFactory创建新的UI元素?当我尝试时,我收到以下错误:

调用线程必须是STA,因为许多UI组件都需要这个.

示例代码

Dim txtBoxList as new List(Of TextBox)

Sub StartThread()
    Dim TS As TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
    Task.Factory.StartNew(Sub() CreateControl(), TS)
End Sub

Sub CreateControl()
    Dim txtBox As New TextBox
    Dispatcher.BeginInvoke(Sub() txtBoxList.Add(txtBox))
End Sub
如果你正在使用WPF,你真的需要留下你可能从古代技术中学到的任何和所有概念,并理解和拥抱 The WPF Mentality.

基本上,您几乎不需要在WPF中的过程代码中创建或操作UI元素.相反,WPF有助于大量使用DataBinding.

The WPF Threading Model不允许您在后台线程中创建或操作UI元素的实例,并将它们添加到由“主”UI线程创建的Visual Tree中.

无论如何,对于这样的事情几乎没有必要,因为创建UI元素在大多数情况下是一个简单的任务,可以(并且必须)由UI线程执行.

您不应该担心Visual Tree,而应该专注于将数据加载到后台线程中,然后将其作为DataContext传递给UI,以便它可以相应地显示您的数据.

这是一个小例子,它使用ItemsControl显示用户列表,这些用户列表在后台线程中异步加载,然后分派到UI线程进行显示:

<Window x:Class="WpfApplication7.AsyncItemsControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Border Background="LightGray" BorderBrush="Black" BorderThickness="1" Margin="2">
                    <StackPanel>
                        <TextBlock Text="{Binding LastName}" Margin="2"/>
                        <TextBlock Text="{Binding FirstName}" Margin="2"/>
                    </StackPanel>
                </Border>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

代码背后:

public partial class AsyncItemsControl : Window
{
    public AsyncItemsControl()
    {
        InitializeComponent();

        var dispatcher = TaskScheduler.FromCurrentSynchronizationContext();

        Task.Factory.StartNew(() => GetUsers())
                    .ContinueWith(x => DataContext = x.Result,dispatcher);

    }

    public List<User> GetUsers()
    {
        // pretend this method calls a Web Service or Database to retrieve the data, and it takes 5 seconds to get a response:
        Thread.Sleep(5000);

        return new List<User>
        {
            new User() {FirstName = "Marty", LastName = "McFly"},
            new User() {FirstName = "Emmett", LastName = "Brown"},
            new User() {FirstName = "Bufford", LastName = "Tannen"}
        };
    }
}

数据项:

public class User
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

结果:

>请注意,该示例使用DataBinding,它不会在过程代码中创建或操作UI元素,而是使用具有简单字符串属性的简单User类进行操作.
>另请注意,在5秒“加载”时间内,UI响应,因为实际工作由后台线程执行.
>此方法允许UI和数据之间更大的分离,这允许UI的更大可扩展性和可定制性,而无需更改底层业务/应用程序逻辑.
>注意ItemsControl如何处理创建和呈现显示3个数据项所需的适当UI元素. “每个项目看起来如何”的实际定义是DataTemplate.>我强烈建议您阅读本答案中链接的材料,以便更深入地了解WPF的工作原理.>旁注:如果你的目标是C#5.0,你可以利用async / await并通过删除所有基于任务的东西来使代码更清晰.我在C#4.0上,因此我无法使用该功能.> WPF Rocks.只需将我的代码复制并粘贴到文件中 – >新项目 – > WPF应用程序并亲自查看结果.>如果您需要进一步的帮助,请告诉我.

网友评论