1

WPF アプリケーションでネットワークを表示したい。ただし、常にレンダリング時にウィンドウがフリーズします。視覚化にはGraphsharp ライブラリを使用します。ネットワークは余分なスレッドで組み立てられます。したがって、おそらくレンダリングになります。では、WPF を使用して UI の一部をバックグラウンドでロードすることは可能ですか?

私のコード:

    _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.Neighbors)
        {
            g.AddEdge(new Edge<object>(p, n));
        }
    }
    return g;
});
OnPropertyChanged("Graph");

XAML:

xmlns:graphsharp="clr-namespace:GraphSharp.Controls;assembly=GraphSharp.Controls"
[...]

<graphsharp:GraphLayout
    Graph="{Binding ElementName=root, Path=Graph}"
    LayoutAlgorithmType="LinLog"
    OverlapRemovalAlgorithmType="FSA"
    HighlightAlgorithmType="Simple" />
4

1 に答える 1

1

別のスレッドから 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 がグラフを表示するのに時間がかかるのはなぜですか?

AsyncComputeGraphLayoutのプロパティを true に設定します。

<graphsharp:GraphLayout
    Graph="{Binding ElementName=root, Path=Graph}"
    LayoutAlgorithmType="LinLog"
    OverlapRemovalAlgorithmType="FSA"
    HighlightAlgorithmType="Simple" 
    AsyncCompute = "true" />

GraphSharpは、少なくとも 6 年前に放棄されました。Codeplex 自体がシャットダウンされ、現在利用可能なソース コードは、アーカイブされたソースか、このような Github のフォークのいずれかです。

このレポの例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 を使用してバックグラウンドで操作を実行します。

このプロパティは、元のプロジェクト ソース アーカイブにも存在します。

于 2018-10-04T07:23:35.560 に答える