C#中的异步加载 - 优化/正确使用?

时间:2009-07-14 14:34:29

标签: c# optimization

所以我想确保我的应用程序的UI线程上没有发生所有数据库/网络操作。为此,我通常使用BeginInvoke函数进行调用,然后使用Invoke进行实际更新。我不确定我是否正在做正确的事情与应该做的事情相比。任何人都可以提供以下代码的评论:

   private void folderTree_NodeExpandedChanged(object sender, RadTreeViewEventArgs e)
    {
        if (e.Node.Tag != null)
        {
            var path = (string) e.Node.Tag;

            if (!string.IsNullOrEmpty(path))
            {
                if (Directory.Exists(path))
                {
                    folderTree.BeginUpdate();

                    BeginInvoke(
                        new Action(() => GetDirectories(path, e.Node)));

                    folderTree.EndUpdate();
                }
            }
        }
    }

    private void GetDirectories(string path, RadTreeNode parent)
    {
        var dirs = (new DirectoryInfo(path)).GetDirectories();

        Array.ForEach(dirs, d => Invoke(new Action(
                                            () => AddNode(d.Name, d.FullName, parent))));
    }

4 个答案:

答案 0 :(得分:3)

在控件/表单上,BeginInvoke通过消息泵将工作推送到UI线程(该特权产生的开销很小)。所以你已经从UI线程转到了UI线程......我怀疑你想在这里某处BackgroundWorker / ThreadPool或类似的东西......(也许ThreadPool最简单从目前的位置)。

也;您可能不希望同步进行更新工作,并且您不希望线程之间进行大量切换;我将整个阵列传递(或中等大小的块);不是个人记录。

答案 1 :(得分:0)

据我所知,以下电话:

BeginInvoke(new Action(() => GetDirectories(path, e.Node)));

......与这一点差别不大:

GetDirectories(path, e.Node);

它只在调用周围增加了一两层,但是没有异步;这一切都发生在同一个线程上。您需要包含一些机制来将工作推送到另一个线程(BackgroundWorker控件,使用ThreadPool或类似的东西)

答案 2 :(得分:0)

您可能会找到BackgroundWorker类,这是一个更简单的选项。

答案 3 :(得分:0)

我会这样做。虽然没有试过这个代码,但它应该可以工作。

      public class ParameterInfo
        {
          string _path;
          RadTreeNode _parent;
        }          

    if (!ThreadPool.QueueUserWorkItem(new WaitCallback(GetDirectories),  
                                 new ParameterInfo  
                                 {  
                                      _path = path,
                                      _parent = e.Node
                                 }))  
       {  
          //should log, if a thread has not been created  
       }  

         private void GetDirectories(ParameterInfo param)
         {
                var dirs = (new DirectoryInfo(param._path)).GetDirectories();

                Array.ForEach(dirs, d => BeginInvoke( new Action( 
                            () => AddNode(d.Name, d.FullName, param._parent) )
                            ));
         }