WPF - 为什么UI锁定?

问题描述 投票:0回答:1

如果我们使用基于任务的异步模式与async和await关键字,则UI锁定没有问题。例如,我们可以花10秒钟从服务器加载数据,并愉快地同时显示等待指示器。但是,在UI线程上运行复杂任务时,线程会锁定,等待指示器中的动画会冻结。

当然,一种策略可能是完全避免大量的UI,但在这种情况下,这不是一个真正的选择。我正在将数百个TreeViewItem加载到屏幕上。这显然导致UI锁定。

我已经尝试将这项工作放在控件的Dispatcher上,但它没有帮助:

   var action = new Action(() =>
    {

       SchemaTree.Items.Clear();

       foreach (var assemblyStructure in assemblyStructures)
       {
           var assemblyNode = CreateTreeNode(SchemaTree.Items, assemblyStructure.Assembly.Name.Replace("Adapt.Model.", string.Empty), assemblyStructure.Assembly, "/Icons/Schema.PNG");

           foreach (var theNameSpace in assemblyStructure.Namespaces)
           {
               var namespaceNode = CreateTreeNode(assemblyNode.Items, theNameSpace.TheNamespace.Name, theNameSpace.TheNamespace, "/Icons/Namespace.PNG");

               foreach (var classInfo in theNameSpace.Classes)
               {
                   CreateClassInfoNode(theNameSpace, classInfo, namespaceNode);
               }
           }
       }
   });

    await SchemaTree.Dispatcher.BeginInvoke(action, DispatcherPriority.Background, null);

如果我将工作转移到Task with Task.Run,​​它实际上会阻止UI锁定,但很明显,我遇到了一个交叉线程违规。

  var action = new Action(async () =>
        {
            await Task.Run(() =>
            {
                SchemaTree.Items.Clear();

                foreach (var assemblyStructure in assemblyStructures)
                {
                    var assemblyNode = CreateTreeNode(SchemaTree.Items, assemblyStructure.Assembly.Name.Replace("Adapt.Model.", string.Empty), assemblyStructure.Assembly, "/Icons/Schema.PNG");

                    foreach (var theNameSpace in assemblyStructure.Namespaces)
                    {
                        var namespaceNode = CreateTreeNode(assemblyNode.Items, theNameSpace.TheNamespace.Name, theNameSpace.TheNamespace, "/Icons/Namespace.PNG");

                        foreach (var classInfo in theNameSpace.Classes)
                        {
                            CreateClassInfoNode(theNameSpace, classInfo, namespaceNode);
                        }
                    }
                }
            });

        });


        await SchemaTree.Dispatcher.BeginInvoke(action, DispatcherPriority.Background, null);

关于如何告诉UI减少这项工作的优先级以使等待指示器有机会动画,以及整个UI没有锁定的任何想法?

wpf multithreading locking dispatcher unresponsive-progressbar
1个回答
0
投票

我原来问题的答案是Dispatcher(处理消息泵送)以先进先出顺序执行所有操作,而不是多线程。这意味着如果您使用消息填充Dispatcher,UI将锁定。值得庆幸的是,问题很容易解决。我需要做的就是打电话

await Dispatcher.Yield(); 

在循环中,问题神奇地消失了。它的作用是允许在创建节点之间执行其他UI工作。

此答案是占位符,直到此处添加更多详细信息。

© www.soinside.com 2019 - 2024. All rights reserved.