Если мы используем асинхронный шаблон на основе задач с асинхронными и ожидающими ключевыми словами, проблем с блокировкой пользовательского интерфейса не возникает. Например, мы можем потратить 10 секунд на загрузку данных с сервера и одновременно с радостью отобразить индикатор ожидания. Однако при выполнении сложных задач в потоке пользовательского интерфейса поток блокируется, а анимация в индикаторе ожидания просто зависает.
Конечно, одной из стратегий может быть полное отсутствие здоровенного пользовательского интерфейса, но в данном случае это не совсем вариант. Я загружаю сотни TreeViewItems на экран. Это явно вызывает блокировку пользовательского интерфейса.
Я попытался поместить работу в диспетчер элемента управления следующим образом, но это не помогает:
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.Run, он на самом деле останавливает блокировку пользовательского интерфейса, но, очевидно, я получаю перекрестное нарушение.
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);
Есть ли какие-либо идеи о том, как сказать пользовательскому интерфейсу уменьшить приоритет этой работы, чтобы у индикатора ожидания была возможность анимировать, а весь пользовательский интерфейс не блокировался?