2009-09-15 4 views
0

У меня есть дерево, использующее BackGround, чтобы добавлять узлы при расширении. После разворачивания я вывешиваю сообщение «Загрузка ..» и удаляю его после загрузки узлов. Он работает отлично и все. Теперь я хочу изменить загружаемое сообщение на «Загрузка ... узла n/n». Я смог это сделать, но проблема в том, что это сообщение не отображается (обновлено до) , а выполняет операцию добавления узлов, но после того, как оно завершено.. Я не мог понять, что я делаю неправильно, и я надеюсь, что кто-то может пролить свет на это.Изменение значения узла в асинхронном TreeView

Вот мой код. Я отлажена 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 
} 

ответ

0

(основная) проблема с вашим bw_ProgressChanged. Ему не нужно ничего вызывать, потому что задача Bgw - синхронизировать ProgressChanged. Я не боляю, но все равно теряю 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(), можно использовать Invoke на AddSubNodes метод(). В результате 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 в 'т'.

+0

Большое спасибо. Как кто-то, кто только начал использовать BackgroundWorker, я хотел бы задать две вещи: 1. Не работает ли в отдельной теме? Таким образом, не должны ли мои приложения AddSubNodes() работать в этом отдельном потоке? 2. Если мне нужно выполнить работу в RunWorkerCompleted, в чем смысл DoWork? Я предполагаю, что у меня что-то отсутствует с BackGroundWorker. – dstr

+0

1) Да, DoWork is async, но Invoke отталкивает (все) работу обратно к основной теме. 2) Вы должны использовать BGW для выполнения большей части работы без GUI (выборка данных для узлов) и касаться только GUI через Invoke, UpdateProgress или Completed. –

+0

Я переместил вызов AddSubNodes() из DoWork в RunWorkerCompleted, дерево все еще зависает во время работы. Пытался вызвать его, так же повесить трубку. Что случилось с этим? – dstr