質問

BackGroundワーカーを使用してツリービューを開いて、ノードを展開するときにノードを追加します。 「Loading ..」を表示します;展開後にメッセージを表示し、ノードがロードされた後に削除します。それはすべて正常に動作します。次に、読み込みメッセージを「Loading ... node n / n」に変更します。私はそれを行うことができましたが、問題は、ノードの追加操作を行っている間は完了した後このメッセージが表示(更新)されないことです。私が間違っていることを理解できず、誰かがこれに光を当てることを望んでいます。

これが私のコードです。 SetValueメソッドをデバッグし、ノードテキストを正しく更新しましたが、操作の終了まで表示されません。

private void t_AfterExpand(object sender, NodeEventArgs e)
{
    t.AppendNode(new object[] { "Loading.." }, e.Node);
    bw.RunWorkerAsync(new object[] { e.Node });
}

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    t.Invoke(new MethodInvoker( () => AddSubNodes(e.Argument) ));
    e.Result = e.Argument;
}

private void AddSubNodes(object arg)
{
    object[] args = arg as object[];
    TreeListNode parentNode = args[0] as TreeListNode;

    int nodeCount = 10;
    for (int i = 0; i < nodeCount; i++)
    {
        t.AppendNode(new object[] { "node cell text" }, parentNode);
        bw.ReportProgress(i, new object[]{ parentNode, "node: " + i.ToString() + "/" + nodeCount.ToString()});
    }
}

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    object[] args = e.UserState as object[];
    TreeListNode parentNode = args[0] as TreeListNode;
    string percentMsg = args[1].ToString(); //node: n/n message

    t.Invoke(new MethodInvoker(() => parentNode.Nodes[0].SetValue(0, percentMsg))); //change "Loading.." to "node: n/n"
    //parentNode.Nodes[0].SetValue(0, mesaj);
}

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    object[] result = e.Result as object[];
    TreeListNode node = result[0] as TreeListNode;

    node.Nodes.RemoveAt(0); //remove loading text
}
役に立ちましたか?

解決

(メイン)問題は、bw_ProgressChangedにあります。 ProgressChangedを同期するのはBgwの仕事であるため、何も呼び出す必要はありません。けがはしませんが、とにかくInvokeを失います。

変更が表示されないのは、Update()がないためです。

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    object[] args = e.UserState as object[];
    TreeListNode parentNode = args[0] as TreeListNode;
    string percentMsg = args[1].ToString(); //node: n/n message

    parentNode.Nodes[0].SetValue(0, percentMsg); //change "Loading.." to "node: n/n"
    parentNode.TreeView.Update(); // or Form.Update

}

bw_DoWork()には別の問題があります。AddSubNodes()メソッドでInvokeを使用します。その結果、コードの99%が完全にメインスレッドで実行され、ソリューションはマルチスレッド化されていません。

次のようなことをします:

//untested
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
//    t.Invoke(new MethodInvoker( () => AddSubNodes(e.Argument) ));
    object[] args = arg as object[];
    TreeListNode parentNode = e;

    var newNodes = new List<TreeNode>();

    int nodeCount = 10;
    for (int i = 0; i < nodeCount; i++)
    {
       // t.AppendNode(new object[] { "node cell text" }, parentNode);
        newNodes.Add(new object[] { "node cell text" }); // ???
        bw.ReportProgress(i, new object[]{ parentNode, "node: " + i.ToString() + "/" + nodeCount.ToString()});
    }

    // e.Result = e.Argument;
    e.Result = newNodes;
}

そして、bw_RunWorkerCompletedで、newNodesの要素を 't'にすばやく追加します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top