繁体   English   中英

C#-将控件从线程转移到另一个

[英]C# - Transfering a control from a thread to another one

窗口中填充的内容越多,将其完全加载所花费的时间就越多,并且用户只有在完成后才能使用任何控件。

所以我想到了以下几点:

使窗口中没有控件,并在另一个线程(例如BackgroundWorker)上创建它们。 然后,这些控件将逐渐添加到主网格中,因此用户可以使用第一个控件,而不必等待其余的控件被创建。

为了将其变为现实,我已经尝试使用一些技术。 最后一个尝试使用Invoke,实际上,我既不知道它如何工作,也不知道如何使用。

public MainWindow()
    {
        InitializeComponent();

        Thread t = new Thread(new ThreadStart(CreateControls));
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }

private void CreateControls()
    {
        Button btn = new Button();
        btn.Width = 90;
        btn.Height = 30;
        btn.Background = Brushes.Black;
        btn.Foreground = Brushes.White;
        btn.Content = "Click me";

        this.Dispatcher.BeginInvoke((Action)delegate
        {
            Dispatcher.Invoke((Action)(() =>
            {
                MainGD.Children.Add(btn);
            }));
        });
    }

MainGD.Children.Add(btn); 我收到: 调用线程无法访问此对象,因为另一个线程拥有它。

在我的研究中,我发现了将按钮创建内容放入Invoke中的方法,如下所示:

this.Dispatcher.BeginInvoke((Action)delegate
    {
        Dispatcher.Invoke((Action)(() =>
        {
            Button btn = new Button();
            btn.Width = 90;
            btn.Height = 30;
            btn.Background = Brushes.Black;
            btn.Foreground = Brushes.White;
            btn.Content = "Click me";

            MainGD.Children.Add(btn);
        }));
    });

但是我不想在主线程中创建控件。
有人可以帮我吗?
那有可能吗?


关键是:是否可以在另一个线程内创建GUI控件并将其转移到GUI线程? 那就是我想做的。

好主意,但是恐怕那行不通。 用户界面代码必须在GUI线程上。

BackgroundWorkers和线程用于执行工作 ,而GUI线程用于执行用户界面。 “工作”是诸如数字运算或数据库查找之类的事情:这些事情最终会将其结果发送到GUI线程进行显示。

如果您的表单花费的时间太长,无法纯粹从向其添加控件中加载表单,则可能是控件太多了-看看是否可以重新设计它。

听起来像异步/等待可能在这里有用。 我在一个项目中工作,该项目的窗口UI由顶部的一些菜单项,中间的自定义控件区域和底部的一些操作按钮(如“确定”,“取消”)组成。 在创建窗口时,将创建菜单项和操作按钮。 但是,中间区域的控件是使用异步调用生成的。

我们使用ObservableCollection作为中间区域中ItemsControl的数据源。 然后,在Window.ContentRendered事件中(因此在绘制窗口之后),我们“等待”了一个构建自定义控件的方法。

这是MyWindow背后的代码片段:

public partial class MyWindow : Window
{
    /* Window c'tor, other methods/props ommited */

    // Load our custom controls asynchronously after the window is rendered
    private async void MyWindow_ContentRendered(object sender, EventArgs e)
    {
        // kick off the asynchronous call to create a custom controls
        await CreateCustomControls();
    }

    // Asynchronously adds MyCustomControls to the ObservableCollection 
    // (we actually used a separate static class that contained our definitions
    // and created the controls) 
    private async Task CreateCustomControls()
    {
        // the def describes what you want to build and is not detailed here
        foreach (var controlDef in MyCustomControlDefinitions)
        {
            // create a control based on the definition
            var newControl = await CreateMyCustomControl(controlDef);

            // Don't add the control until it is completely built
            MyCustomControls.Add(newControl);
        }
    }

    //The (bindable) collection of custom controls
    public ObservableCollection<MyCustomControl> MyCustomControls
    {
        get { return (ObservableCollection<MyCustomControl>)GetValue(MyCustomControlsProperty); }
        set { SetValue(MyCustomControlsProperty, value); }
    }

    public static readonly DependencyProperty MyCustomControlsProperty =
    DependencyProperty.Register("MyCustomControls", typeof(ObservableCollection<MyCustomControl>),
        typeof(MyWindow), new PropertyMetadata(new ObservableCollection<MyCustomControl>()));

}

这是MyWindow XAML的代码段:

<Window>
    <Grid>
        <!-- Scrollable Panel for MyCustomControls -->
        <ScrollViewer>
            <ItemsControl ItemsSource="{Binding MyCustomControls}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </ScrollViewer>
    </Grid>
</Window>

重要的是要注意,它只能提供“可感知的”性能提升。 我们所做的只是允许窗口在创建其余控件时有所用。 因此,用户可以立即与顶部和底部控件进行交互(显示窗口时),并且一旦将自定义控件添加到ObservableCollection中,用户也可以与它们进行交互。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM