将用户控件添加到网格异步[重复]

Posted

技术标签:

【中文标题】将用户控件添加到网格异步[重复]【英文标题】:Adding UserControls to Grid Asynchronously [duplicate] 【发布时间】:2021-09-15 12:13:02 【问题描述】:

我正在使用 WPF 应用程序,并且在应用导航时遇到问题,屏幕冻结,所以我想实现异步

我的导航方法:我创建一个网格并将用户控件添加到该网格的 children 属性 由于我在许多不同的用户控件上有这么多 UI 元素,它会冻结应用程序

我想在加载窗口时添加一个异步用户控件,我的想法是使用 async await 关键字,但显然我使用错误,我研究过,不明白为什么建议使用调度程序甚至在有异步等待之后,所以我想按照这种方式(异步/等待)

这只是真实交易的一个示例问题

这是代码

private async void grid1_Loaded(object sender, RoutedEventArgs e)
    
        txtb1.Text = "";

        var watch = System.Diagnostics.Stopwatch.StartNew();

        await gy();

        watch.Stop();
        var elapsedtm = watch.ElapsedMilliseconds;

        txtb1.Text += $"TOTAL TIME elapsedtm \n\n\n";
    

    private async Task gy() 
    
        ////////////
        
        Y1 child1 = new Y1();
        await Task.Run(() => grid1.Children.Add(child1));
        
        ///////////
    

【问题讨论】:

您只能在创建 grid1 的线程中访问grid1.Children,即不能从任务操作中访问。也许使用 DispatcherTimer 在块中添加子元素。 通常向 UI 添加元素很快。通常是一些需要时间的数据处理。或者您是说您正在创建一些 UI 元素,而数据处理可以忽略不计,这会降低您的应用程序的速度? @Clemens 那么你是说使用 Async 和 await 是行不通的,而 dispathcher.begininvoke 就是这样,我知道如何使用 Dispatcher 执行它们我想学习异步方式 @Enigmativity 好吧,我正在使用一个名为 MaterialDesignforXAML 的库,我在用户控件中使用这些 UI 元素,并将这些用户控件添加到网格中,在添加了这些众多的用户控件之后,我只是根据几个按钮点击事件 不,我不是这么说的。 Async/await 和 Dispatcher 不是相互排斥的。两者都可以很好地协同工作。如果您要访问具有线程关联性的对象 - 例如UI 元素 - 从创建它的线程以外的线程,您必须通过对象的 Dispatcher 或在同一线程中创建的 Progress 实例来执行此操作。请注意,Task.Run 通常在与线程池不同的线程上运行。 【参考方案1】:
        private async void grid1_Loaded(object sender, RoutedEventArgs e)
        
            txtb1.Text = "";

            var watch = System.Diagnostics.Stopwatch.StartNew();

            //Asynchronous execution of the "gy" method in the UI thread.
            await Dispatcher.InvokeAsync(gy);

            watch.Stop();
            var elapsedtm = watch.ElapsedMilliseconds;

            txtb1.Text += $"TOTAL TIME elapsedtm \n\n\n";
        

        // This method can only be called on the main UI thread.
        private void gy()
        
            ////////////

            UIElement child1 = new Y1();
           grid1.Children.Add(child1);

            ///////////
        

如果 gy 方法中有一些长期操作不使用 UI 元素,并且您需要将主 UI 线程从它们的执行中释放出来,那么这个选项:

        private async void grid1_Loaded(object sender, RoutedEventArgs e)
        
            txtb1.Text = "";

            var watch = System.Diagnostics.Stopwatch.StartNew();

            
            await gy();

            watch.Stop();
            var elapsedtm = watch.ElapsedMilliseconds;

            txtb1.Text += $"TOTAL TIME elapsedtm \n\n\n";
        

        private async Task gy()
        
            // Here's some lengthy code, but in which there are no calls to UI elements.
            ////////////

            await grid1.Dispatcher.BeginInvoke(new Action(() =>
             
                 UIElement child1 = new Label()  Content = "Hello" ;
                 grid1.Children.Add(child1);
             ));

            ///////////
            // Here's some lengthy code, but in which there are no calls to UI elements.
        

【讨论】:

以上是关于将用户控件添加到网格异步[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在网格上动态重新布局用户控件?

将数据加载到数据网格时 C#/WPF 主窗口冻结

将内容编辑器 Web 部件添加到 sharepoint 2010 用户控件

在 WPF 的网格中显示对其他控件的控件

当鼠标在 UC 区域之外时,WPF 用户控件可以检测到 MouseMovement

如何从后面的用户控件代码访问用户控件所在的主窗口上的网格列