gpt4 book ai didi

wpf - TaskFactory 新 UI 创建

转载 作者:行者123 更新时间:2023-12-04 14:03:13 29 4
gpt4 key购买 nike

如何使用 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 线程执行的微不足道的任务。

与其担心可视化树,您应该专注于在后台线程中加载您的数据,然后作为 DataContext 传递给 UI,以便它可以相应地显示您的数据。

这是一个使用 ItemsControl 显示用户列表的小示例,这些用户列表在后台线程中异步加载,然后分派(dispatch)到 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; }
}

结果:

enter image description here

  • 请注意,该示例使用了 DataBinding,它不会在过程代码中创建或操作 UI 元素,而是使用简单的 User 类和简单的 string 进行操作属性。

  • 另请注意,在 5 秒的“加载”时间内,UI 是响应式的,因为实际工作是由后台线程执行的。

  • 这种方法允许在 UI 和数据之间实现更大程度的分离,从而允许 UI 具有更大的可扩展性和可定制性,而无需更改底层业务/应用程序逻辑。

  • 请注意 ItemsControl 如何负责创建和呈现显示 3 个数据项所需的适当 UI 元素。 “每个项目的外观”的实际定义是 DataTemplate

  • 我强烈建议阅读贯穿此答案的链接 Material ,以便更深入地了解 WPF 的一般工作原理。

  • 旁注:如果您的目标是 C# 5.0,则可以利用 async/await 并通过删除所有基于 Task 的内容来使此代码更清晰。我使用的是 C# 4.0,因此我无法使用该功能。

  • WPF Rocks。只需将我的代码复制并粘贴到 File -> New Project -> WPF Application 中,然后亲自查看结果。

  • 如果您需要进一步的帮助,请告诉我。

关于wpf - TaskFactory 新 UI 创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23303985/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com