2015-06-26 37 views
1

是否有可能通過多線程(Task.Run等)或任何其他好技術幫助改善以下功能的響應時間?活動目錄提高在C#中的性能 - WPF

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);     
    } 
} 
+0

您是否看到緩慢?您目前對這種方法的性能有什麼經驗? –

+0

是的,隨着組中用戶數量的增加,性能越來越差。如果任何組有2個用戶(5秒)7個用戶(12-14秒)回覆! – user2229874

+0

代碼看起來非常直截了當,我能想到的唯一的事情是網絡問題是延遲問題,或者在分配成員變量後嘗試設置machineContext = null也在您的方法內放置UserCollection對象,除非您沒有顯示完整該對象的範圍如果不知道FillUserList被調用的頻率,我無法分辨。 – MethodMan

回答

0

嘗試處置組和機器方面,如下圖所示,

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(); 
     } 
    } 
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"); 
    } 
}