【问题标题】:Active Directory improve performance in C# - WPFActive Directory 提高 C# 中的性能 - WPF
【发布时间】:2015-06-26 20:34:17
【问题描述】:

是否可以借助多线程(Task.Run 等)或任何其他好的技术来提高以下函数的响应时间?

UserCollection = new ObservableCollection<User>();

public void FillUserList(string machineName, string groupName)
{
    UserCollection.Clear();

    if (string.IsNullOrEmpty(machineName) || string.IsNullOrEmpty(groupName))
        return;

    var machineContext = new PrincipalContext(ContextType.Machine, machineName, null, ContextOptions.Negotiate);
    var group = GroupPrincipal.FindByIdentity(machineContext, groupName);

    var members = group.GetMembers();

    foreach (var member in members)
    {
        var user = new User { DisplayName = member.Name, UserId = member.SamAccountName };
        UserCollection.Add(user);                
    }
}

【问题讨论】:

  • 你看到慢了吗?对于这种方法的性能,您目前的经验是什么?
  • 是的,随着组内用户数的增加,性能越来越差。如果任何组有 2 个用户(5 秒)7 个用户(12-14 秒)回复!
  • 代码看起来很简单我唯一能想到的就是网络问题是延迟问题,或者在你分配成员​​变量后尝试设置 machineContext = null 也在你的方法中放置 UserCollection 对象除非您没有显示该对象的全部范围,否则我无法知道 FillUserList 被调用的频率......
  • 基本上,我创建了具有两个文本框的 WPF 应用程序。用户提供机器名和组名。输入组名后,在扩展器的帮助下,我在每个组下方显示与相应组关联的用户(两个标签)。这个函数用的很频繁。

标签: c# wpf multithreading performance active-directory


【解决方案1】:

正如其他人已经注意到的那样,代码非常简单,实际上没有任何可能在多个线程中运行(如果我弄错了,请告诉我)。虽然可能会稍微改善您的方法的响应时间,但不幸的是,我认为它不会很快。

有时事情只是想度过他们的甜蜜时光,作为开发人员,我们只需要接受它并欺骗用户认为他们根本没有等待。

所以,我的建议来了:

您正在同一个线程中同步运行此方法 (FillUserList),用于处理事件并执行与 GUI 相关的所有其他操作(UI 线程)。当您的方法忙于加载用户时,这会使应用程序“冻结”。通常,当您无法避免更长的加载时间时,您会将繁重的任务重定向到后台(后台线程,甚至是同一个线程,但您异步运行它),同时保持 UI 完全响应。

我使用与您当前的场景非常相似的BackgroundWorker 准备了一个示例解决方案。唯一的区别是我使用的是控制台应用程序,而不是 WPF。但是,您应该能够轻松修改我的代码以在您的场景中工作。

class Program
{
    static List<string> UserCollection = null;

    static void Main(string[] args)
    {
        FillUserList("Hello", "World");
        Console.ReadLine();
    }

    public static void FillUserList(string machineName, string groupName)
    {
        var worker = new BackgroundWorker();
        var temporaryUserCollection = new List<string>();

        worker.DoWork += (s, ea) => { YourLongRunningTask(machineName, groupName, temporaryUserCollection); };
        worker.RunWorkerCompleted += (s, ea) => { UserCollection = temporaryUserCollection; Console.WriteLine("Loaded."); };
        worker.RunWorkerAsync();

        // I'm writing to the console, but you should show
        // some sort of loading indicator (spinner, "please wait" dialog, progress bar, etc.) in this line
        Console.WriteLine("Loading...");
    }

    public static void YourLongRunningTask(string machineName, string groupName, List<string> userCollection)
    {
        // Paste your current FillUserList code here
        Thread.Sleep(5000);
        userCollection.Add("A");
        userCollection.Add("B");
        userCollection.Add("C");
    }
}

【讨论】:

    【解决方案2】:

    尝试如下处理组和机器上下文,

       group.Dispose(); 
       machineContext.Dispose(); 
    

    这可能有助于提高性能。

    代码:

        UserCollection = new ObservableCollection<User>();
    
        public void FillUserList(string machineName,string groupName)
        {
            UserCollection.Clear();
            if (string.IsNullOrEmpty(machineName) || string.IsNullOrEmpty(groupName))
                return;
    
            var machineContext = new PrincipalContext(ContextType.Machine, machineName, null, ContextOptions.Negotiate);
            var group = GroupPrincipal.FindByIdentity(machineContext, groupName);
    
            var members = group.GetMembers();
    
            foreach (var member in members)
            {
                var user = new User { DisplayName = member.Name, UserId = member.SamAccountName };
                UserCollection.Add(user);                
            }
    
           //try disposing the objects
           group.Dispose(); 
           machineContext.Dispose(); 
        }
    

    注意:您也可以使用 using 语句代替 .dispose。请看下面的代码,

        UserCollection = new ObservableCollection<User>();
    
        public void FillUserList(string machineName,string groupName)
        {
            UserCollection.Clear();
            if (string.IsNullOrEmpty(machineName) || string.IsNullOrEmpty(groupName))
                return;
    
            using(var machineContext = new PrincipalContext(ContextType.Machine, machineName, null, ContextOptions.Negotiate)){
    
              var group = GroupPrincipal.FindByIdentity(machineContext, groupName);
    
              var members = group.GetMembers();
    
              foreach (var member in members)
              {
                 var user = new User { DisplayName = member.Name, UserId = member.SamAccountName };
                 UserCollection.Add(user);                
              }
    
             //try disposing the objects
             group.Dispose(); 
           }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-23
      • 2017-01-05
      • 2010-11-26
      • 1970-01-01
      相关资源
      最近更新 更多