2013-05-01 43 views
0

在我的應用程序打開約70服務器上平均每個具有8個數據庫連接(服務器分爲環境即開發,生產,UAT,坐,培訓,雜項,QA) 。 應用程序將檢查每個數據庫中是否存在用戶,並在用戶存在時提取詳細信息。 我已經使用了一種方法來調用服務,這個方法將傳遞用戶ID作爲輸入inturn服務將檢查跨數據庫的用戶並獲取詳細信息。 整個過程花費的時間太長,UI中的空閒時間大約爲5-10分鐘。可以mutithreading被用來進行性能調整我的應用程序

我們如何調整此應用程序的性能?我想在環境的基礎上實現多線程和獲取鎖定。但我不確定是否可以在應用程序中使用返回類型以及輸入參數調用方法。

請提出一種提高性能的方法。

public List<AccessDetails> GetAccessListOfMirror(string mirrorId,string server) 
     { 
      List<AccessDetails> accessOfMirror = new List<AccessDetails>(); 
      string loginUserId = SessionManager.Session.Current.LoggedInUserName; 
      string userPassword = SessionManager.Session.Current.Password; 
      using (Service1Client client = new Service1Client()) 
      { 
       client.Open(); 
        accessOfMirror = client.GetMirrorList(mirrorId, server, loginUserId, userPassword); 
      } 

      return accessOfMirror; 
     } 

服務方法

public List<AccessDetails> GetMirrorList(string mirrorId, string server, string userId, string userPassword) 
     { 

      string mirrorUser = mirrorId.ToString(); 
      List<ConnectionStringContract> connectionStrings = new List<ConnectionStringContract>(); 
      try 
      { 
       connectionStrings = GetConnectionString(server); 
      } 
      catch (FaultException<ServiceData> exe) 
      { 
       throw exe; 
      } 

      AseConnection aseConnection = default(AseConnection); 
      List<AccessRequest> mirrorUsers = new List<AccessRequest>(); 
      List<FacetsOnlineAccess> foaAccess = new List<FacetsOnlineAccess>(); 
      List<AccessDetails> accessDetails = new List<AccessDetails>(); 
      AccessDetails accDetails = new AccessDetails();        
      AccessRequest access; 
      if (!String.IsNullOrEmpty(server)) 
       connectionStrings = connectionStrings.Where(x => x.Server == server).ToList(); 
      foreach (ConnectionStringContract connection in connectionStrings) 
      { 
       string connectionString = connection.ConnectionString; 

       AseCommand aseCommand = new AseCommand(); 
       using (aseConnection = new AseConnection(connectionString)) 
       { 
        try 
        { 
         aseConnection.Open(); 
         try 
         { 
          List<Parameter> parameter = new List<Parameter>(); 
          Parameter param; 
          param = new Parameter(); 
          param.Name = "@name_in_db"; 
          param.Value = mirrorUser.ToLower().Trim(); 
          parameter.Add(param); 
          int returnCode = 0; 
          DataSet ds = new DataSet(); 
          try 
          { 
           ds = DataAccess.ExecuteStoredProcedure(connectionString, Constant.SP_HELPUSER, parameter, out returnCode); 
          } 
          catch (Exception ex) 
          { 

          } 
          if(ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0) 
          { 
           foreach (DataRow row in ds.Tables[0].Rows) 
           { 
            access = new AccessRequest(); 
            if (row.ItemArray[0].ToString() == mirrorUser) 
             access.Group = row.ItemArray[2].ToString(); 
            else 
             access.Group = row.ItemArray[0].ToString(); 
            access.Environment = connection.Environment.Trim(); 
            access.Server = connection.Server.Trim(); 
            access.Database = connection.Database.Trim(); 
            mirrorUsers.Add(access); 
           }        

          } 


         } 
         catch (Exception ex) 
         { 

         } 
        } 
        catch (Exception ConEx) 
        { 

        } 
       } 
      } 
      accDetails.AccessList = mirrorUsers; 
      //accDetails.FOAList = foaAccess; 
      accessDetails.Add(accDetails); 
      return accessDetails; 
     } 

預先感謝

回答

1

循環有時會降低速度,尤其是循環內部循環。 I/O操作總是很慢。你和我有一個循環。所以如果你要在並行線程上執行這個I/O操作,性能會增加。

你可以翻譯

foreach (ConnectionStringContract connection in connectionStrings) 
{ 
    ... 
} 

到:

Parallel.ForEach(connectionStrings, connectionString => 
{ 
    ... 
} 

在裏面你應該鎖定常用的變量,如mirrorUsers用鎖。 我認爲這是一個很好的開始。同時我會尋找其他性能問題。

+0

很好的開始確實如此。另外,如果常用變量的使用頻率非常高,而且複製速度很快,則可以將它們複製到lambda表達式中,並且可能會提高性能。不過,一般來說,你想要做的第一件事情就是進行實際的性能測試。確保讓你放慢速度的東西就是你認爲的東西。 – SimpleVar 2013-05-01 08:57:04

+0

@Yorye:我不明白,在這種情況下,lamda會如何提高速度。你能給我們一個例子來清理嗎?是的,測量也非常重要! – 2013-05-01 08:59:03

+0

我的意思是說,鎖定變量可能會減慢速度,因爲只有一個或兩個線程在給定時刻實際運行。爲了最大限度地提高並行性的效率,您需要避免線程之間的依賴關係,因此您可以在lambda中複製變量並自由使用它們。不過,這是一個通用提示。在這種情況下,您顯然希望在並行線程之間共享列表。然而,你可以做的是,每個線程都有一個本地列表,並且最終鎖定外部範圍列表一次,以使用「AddRange」。 – SimpleVar 2013-05-01 09:10:30

-1

您應該能夠利用多線程的沒有太多的麻煩......

你或許應該使用線程池的,這樣你就不會產卵過多的線程都在同一時間運行。你可以閱讀內置的線程池的位置:

http://msdn.microsoft.com/en-us/library/3dasc8as%28v=vs.80%29.aspx

你應該做的是你的foreach循環體內提取到一個靜態方法。任何參數都應該製作成可傳遞給線程的模型。因爲那麼你可以使用ThreadPool.QueueUserWorkItem(object)來啓動線程。

關於多線程寫入同一資源(列表或其他),你可以使用任何一種互斥鎖或線程組件。使用鎖很簡單:

http://msdn.microsoft.com/en-us/library/c5kehkcz%28v=vs.80%29.aspx

+2

假設可以使用.NET 4.0,使用任務並行庫(TPL)而不是使用ThreadPool要容易得多。 – Hanno 2013-05-01 09:42:21

+0

-1:請不要發佈.NET 2.0鏈接,除非答案是特定於.NET 2.0。 – 2013-05-01 10:32:58

相關問題