gpt4 book ai didi

c# - 在 UI 线程上执行长任务

转载 作者:太空宇宙 更新时间:2023-11-03 16:14:57 25 4
gpt4 key购买 nike

我正在开发一个简单的自定义控件,它应该充当菜单系统。它由 2 个按钮组成:Back 和 Home 以及上面的菜单项。ControlTemplate 看起来像这样:

  <ControlTemplate x:Key="FancyColorPickerTemplate">
<menu:BusyDecorator x:Name="BusyDecorator" Style="{StaticResource BusyDecoratorStyle}">
<menu:BusyDecorator.IsBusyIndicatorShowing>
<PriorityBinding>
<Binding Path="IsBusy" RelativeSource="{RelativeSource AncestorType={x:Type CustomControls:Menu}}"/>
</PriorityBinding>
</menu:BusyDecorator.IsBusyIndicatorShowing>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.70*"/>
<RowDefinition Height="0.30*"/>
</Grid.RowDefinitions>

<ItemsControl Grid.Row="0" Name="Part_ItemControl"
ItemTemplateSelector="{StaticResource imgStringTemplateSelector}"
HorizontalAlignment="Center" VerticalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button Grid.Row="1" Name="PART_BackButton" FontSize="20" Content="Back" HorizontalAlignment="Left" />
<Button Grid.Row="1" Name="PART_HomeButton" FontSize="20" Content="Home" HorizontalAlignment="Center" />
</Grid>
</menu:BusyDecorator>
</ControlTemplate>

在 ItemsControl 上有一个 ItemTemplateSelector 用于选择显示元素的 DataTemplate(可以是按钮或 UserControl)。示例:

    <DataTemplate x:Key="ButtonTemplate">
<Grid Margin="10,0,10,0">
<Button Content="{Binding Title}" ></Button>
</Grid>
</DataTemplate>

<DataTemplate x:Key="UserControlTemplate">
<Grid Margin="10,0,10,0">
<CustomControls:ColorPickerUserControl Width="200" Height="200"/>
</Grid>
</DataTemplate>

在 Codebehind 中,我检查单击了哪个元素并在需要时加载子菜单(通过设置 ItemsControl 的 ItemsSource 属性):

 void Menu_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
ItemsControl itemsControl = GetTemplateChild("Part_ItemControl") as ItemsControl;
object item = GetElementFromPoint(itemsControl, e.GetPosition(itemsControl));

if (item != null && item is MenuItem2)
{
MenuItem2 mi = item as MenuItem2;
if (mi.SubMenu != null)
{
IsBusy = true;
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
MenuItems = new ObservableCollection<MenuItem2>(mi.SubMenu.Items);
IsBusy = false;
}));
m_MenuStack.Push(mi.SubMenu);
}
else
{
if (!IsBusy)
{
ExecuteAction(mi.Ac);
}
}
}
else
Console.WriteLine("no item found");
}

上面代码中的 MenuItems 绑定(bind)到 ItemsSource 属性,这将重新评估 ItemsControl 并根据 DataTemplateSelector 应用相应的 DataTemplate。我的代码中的问题是上面的 IsBusy 属性应该显示 BusyDecorator(请参阅 xaml),而 DataTemplate 是一个需要很长时间才能显示的 UserControl。它不起作用,因为我猜 UserControl 正在 UI 线程上加载,以及 IsBusy 属性触发 UI 线程上的操作。

我是不是采用了错误的方法?有什么办法可以做到这一点吗?

最佳答案

您始终可以设置忙碌标志,并在忙碌集的渲染完成后安排 UI 线程上的其余工作。

这里神奇的部分是使用优先级 System.Windows.Threading.DispatcherPriority.Render 调度线程,这使得任务在渲染的同时运行。

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Click="Button_Click_1">LongTask</Button>
<TextBlock Grid.Row="1" Text="{Binding IsBusy}"/>
</Grid>
</Window>

以及背后的代码

using System;
using System.Threading;
using System.Windows;

namespace WpfApplication1
{
public partial class MainWindow : Window
{
public bool IsBusy
{
get { return (bool)GetValue(IsBusyProperty); }
set { SetValue(IsBusyProperty, value); }
}

public static readonly DependencyProperty IsBusyProperty = DependencyProperty.Register("IsBusy", typeof(bool), typeof(MainWindow), new PropertyMetadata(false));

public MainWindow()
{
InitializeComponent();
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
IsBusy = true;
this.Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(2000);

IsBusy = false;
}), System.Windows.Threading.DispatcherPriority.Render, null);
}
}
}

关于c# - 在 UI 线程上执行长任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16030901/

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