没有操作系统允许从另一个线程修改 UI。在您的情况下,虽然您没有尝试在后台更新 UI,但您正在后台组装图形并设置属性。这里没有 UI 工作。如果呈现元素绑定到该属性,它将获得通知、读取属性并更新自身,所有这些都在 UI 线程中。
虽然代码需要改进。任务不是线程,没有理由使用冷任务之Task.Start()
类的。Start()
不保证任务何时运行。该任务仍将被安排在线程池线程上执行,如果那里没有可用线程,则可能会等待。
代码可以简化为:
var graph = await Task.Run(()=> {
var g = new BidirectionalGraph<object, IEdge<object>>();
foreach (MyItem p in _myItemList)
{
g.AddVertex(p);
}
foreach (MyItem p in _myItemList)
{
foreach (MyItem n in p.CallingList)
{
g.AddEdge(new Edge<object>(p, n));
}
}
return g;
};
_graph = graph;
OnPropertyChanged("Graph");
一个更好的主意是使用适当的属性而不是修改字段并引发事件:
public BidirectionalGraph Graph
{
get => _graph;
set
{
_graph=value;
OnPropertyChanged(nameof(Graph));
}
}
...
public async Task MyGraphMethod()
{
Graph=graph;
}
更新
真正的问题似乎是为什么 GraphLayout 需要这么长时间来显示图形?
将AsyncCompute
GraphLayout 的属性设置为 true :
<graphsharp:GraphLayout
Graph="{Binding ElementName=root, Path=Graph}"
LayoutAlgorithmType="LinLog"
OverlapRemovalAlgorithmType="FSA"
HighlightAlgorithmType="Simple"
AsyncCompute = "true" />
GraphSharp 早在 6 年前就被抛弃了。Codeplex 本身已关闭,现在唯一可用的源代码是存档的源代码或 Github 上的分支,例如这个。
此 repo 上的示例显示有一个AsyncCompute
属性将在后台运行布局算法:
<sample:MyGraphLayout x:Name="Layout" LayoutAlgorithmType="ISOM" OverlapRemovalAlgorithmType="FSA" Graph="{Binding}"
AsyncCompute="true" ShowAllStates="false" HighlightAlgorithmType="Simple">
<sample:MyGraphLayout.LayoutParameters>
<isom:ISOMLayoutParameters Width="1200" Height="1200" />
</sample:MyGraphLayout.LayoutParameters>
</sample:MyGraphLayout>
当AsyncCompute为true时,Layout()
控件的方法使用BackgroundWorker在后台执行操作
此属性也存在于原始项目源存档中。