Почему этот многопоточный метод занимает 900 миллисекунд? - PullRequest
1 голос
/ 01 ноября 2010
private void Form1_Load(object sender, System.EventArgs e)
{
    StartToFillTree();
}

private void StartToFillTree( )
{
    try
    {
        tvFolders.Nodes.Clear();
        tvFolders.Nodes.Add( new TreeNode("Loading", -1, -1) );

        Thread explorerThread = new Thread( new ThreadStart( FillTreeInAnotherThread ) );
        explorerThread.Start();
    }
    catch (Exception exc)
    {
        //Do the catch
    }
}

private void FillTreeInAnotherThread()
{
    try
    {
        CreateTree(this.tvFolders);
    }
    catch (Exception exc)
    {
        //Do the catch
    }
}


public void ClearTreeview( TreeView tv ) 
{
    tv.Nodes.Clear();
}

public void AddNodeToTreeview( TreeView tv, TreeNode node ) 
{
    tv.Nodes.Add( node );
}

public void CreateTree(TreeView treeView)
{
    try
    {
        TreeNode hoofdNode = new TreeNode( "NodeNam", 0, 0);
        AddDrivesToHoofdNode(hoofdNode); //This method takes 1 ms

        //This part takes 905 milliseconds if I can believe my profiler !!?? -----
        if( treeView.InvokeRequired )
        {
            treeView.Invoke( new ClearTreeviewDelegate( this.ClearTreeview ), new object[] { treeView } );
            treeView.Invoke( new AddNodeToTreeviewDelegate( this.AddNodeToTreeview ), new object[] { treeView, hoofdNode } );
        }
        else
        {
            treeView.Nodes.Clear();
            treeView.Nodes.Add(hoofdNode);
        }
        //End of 900ms part ?? -----


        AddFavorieteFolders(treeView);//This method takes 1 ms

    }
    catch (Exception ex)
    {
        //Do some catching
    }
}

Ответы [ 4 ]

8 голосов
/ 01 ноября 2010

Вы не можете обновить компоненты пользовательского интерфейса вне потока пользовательского интерфейса. Все эти вызовы Invoke направляют обновления обратно в поток пользовательского интерфейса, снова сериализуя ваше приложение.

Типичным подходом к большим деревьям является загрузка дочерних узлов только при расширении родительского узла, а не попытка заполнить все дерево в начале.

3 голосов
/ 01 ноября 2010

Прежде всего, почему вы используете темы для чего-то такого простого? Выглядит немного чрезмерно разработанным. Но, может быть, вы не показываете нам все?

Также оберните модификации TreeView:

treeView.BeginUpdate();
// modify the tree here.
treeView.EndUpdate();

Для повышения производительности.

3 голосов
/ 01 ноября 2010

InvokeRequired занимает некоторое время, чтобы сделать свою работу.Смотрите это .Особенно "Если дескриптор элемента управления еще не существует, InvokeRequired выполняет поиск в родительской цепочке элемента управления, пока не найдет элемент управления или форму, у которой есть дескриптор окна. Если не удается найти соответствующий дескриптор, метод InvokeRequired возвращаетложный."Так что это займет некоторое время

2 голосов
/ 01 ноября 2010

Вы вызываете BeginUpdate на вашем TreeView элементе управления перед очисткой и добавлением новых узлов, а затем вызываете EndUpdate, когда закончите добавлять узлы?Если вы не сделаете эти вызовы, ваш TreeView попытается перекрасить себя после каждого добавленного узла - в противном случае это может привести к тому, что код, который в остальном нормально работает, будет работать очень медленно, особенно при добавлении большого количества узлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...