首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TaskFactory新UI创建

TaskFactory新UI创建
EN

Stack Overflow用户
提问于 2014-04-25 22:16:46
回答 1查看 857关注 0票数 2

如何使用TaskFactory创建新的UI元素?当我尝试时,我会得到以下错误:

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

示例代码

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-25 23:23:53

如果您正在使用WPF,那么您确实需要抛弃您可能从古老的技术中学到的任何和所有的概念,并理解和接受The WPF Mentality

基本上,您几乎不需要在WPF中的过程代码中创建或操作UI元素。相反,WPF允许自己大量使用DataBinding

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

无论如何,这样的事情几乎是零需要的,因为在大多数情况下,创建UI元素是一项琐碎的任务,可以(而且必须)由UI线程执行。

与其担心Visual,不如将数据加载到后台线程中,然后作为DataContext传递给UI,以便它能够相应地显示数据。

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

代码语言:javascript
复制
<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>

代码背后:

代码语言:javascript
复制
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"}
        };
    }
}

数据项:

代码语言:javascript
复制
public class User
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

结果:

  • 请注意,该示例使用DataBinding,它没有在过程代码中创建或操作UI元素,而是使用具有简单string属性的简单User类操作。
  • 还请注意,在5秒“加载”时间内,UI是响应的,因为实际工作是由后台线程执行的。
  • 这种方法允许UI和数据之间更好地分离,这允许UI具有更大的可伸缩性和可定制性,而无需更改底层业务/应用程序逻辑。
  • 请注意ItemsControl是如何创建和呈现显示3个数据项所需的批准UI元素的。“每个项目的外观”的实际定义是DataTemplate
  • 我强烈建议阅读相关的材料,尽管这个答案更深入地理解WPF的工作原理。
  • 附带注意:如果您正在使用C# 5.0,您可以通过删除所有基于Task的内容来利用async / await并使代码更简洁。我在C# 4.0上,所以这个特性对我来说是不可用的。
  • WPF Rocks.只需将我的代码复制并粘贴到File -> New Project -> WPF Application中,并亲自查看结果。
  • 如果你需要进一步的帮助,请告诉我。
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23303985

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档