2015-08-17 72 views
0

我已經編寫了一個代碼來在網絡中ping 300個系統,並將狀態(離線/在線)更新到Access數據庫文件中。如何提高以下代碼的性能?

我正在使用任務類。 Pinging 300系統只需要不到一秒的時間,但將這些狀態插入數據庫文件需要將近30到40秒。

它降低了我的應用程序的性能,請查看我的代碼。如果

主要方法

private static void Main(string[] args) 
    { 
     #region Reading IpAdddress 

     List<string> address = new List<string>(); 
     Task t = Task.Run(() => 
     { 
      var reader = new StreamReader(File.OpenRead(Environment.CurrentDirectory + @"\address.csv")); 
      while (!reader.EndOfStream) 
      { 
       var lines = reader.ReadLine(); 
       var values = lines.Split(';'); 
       address.Add(values[0]); 
      } 
     }); 

     #endregion 

     Stopwatch timeSpan = Stopwatch.StartNew(); 

     t.Wait(); 


     AsyncPingTask(address).Wait(); 
     Console.WriteLine("Update Completed"); 

     Console.WriteLine(timeSpan.ElapsedMilliseconds); 
     Console.ReadLine(); 
    } 

坪任務

private static async Task AsyncPingTask(List<string> ipaddress) 
    { 
     try 
     { 
      Console.WriteLine("Ping Started");        

      var pingTasks = ipaddress.Select(ip => 
      { 
       return new Ping().SendTaskAsync(ip);      
      }).ToList(); 

      var replies= await Task.WhenAll(pingTasks); 
      Console.WriteLine("Ping Completed"); 

      int online, offline; 
      online = 0; 
      offline = 0; 
      Console.WriteLine("Update in progress...");     

      foreach (var pingReply in replies) 
      { 
       var status = ""; 
       if (pingReply.Reply.Status.ToString() == "Success") 
       { 
        online++; 
        status = "Online"; 

       } 
       else 
       { 
        status = "Offline"; 
        offline++; 
       } 
       Program p = new Program();      
       Parallel.Invoke(() => 
       { 
        p.UpdateSystemStatus(pingReply.Address, status); 
       }); 

      } 


      Console.WriteLine("Online Systems : {0}", online); 
      Console.WriteLine("Offline Systems : {0}", offline); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
      throw; 
     } 

    } 

更新狀態的方法

private void UpdateSystemStatus(string ipAddr, string status) 
{ 
    using (OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\/Topology.accdb")) 
    { 
     string query = "UPDATE SystemStatus SET [email protected] WHERE IP='" + ipAddr + "'"; 

     OleDbCommand cmd = new OleDbCommand(query, con); 
     con.Open(); 
     cmd.Parameters.AddWithValue("@SystemStatus", status); 

     cmd.ExecuteNonQuery();   
    } 
} 
+2

[CodeReview.SE]會不會更好? –

+0

每次ping檢查你創建新的'OleDbConnection'。這可能需要一些時間。我想這將是更好的,如果你移動創建連接到你的主要方法,只是通過創建的連接作爲參數.. –

+0

其實我正在讀取列表中的整體ping狀態並插入到數據庫。 –

回答

1

這不是我的AR ea的專業知識,但我的猜測是,爲每個更新的記錄創建一個新的OleDbConnection有很多開銷。我可以想象,它至少必須在文件系統中打開訪問數據庫,檢查權限,解析一堆東西等等。連接創建一次的方法可能會更好。我也看到有一些事務機制可能會提高性能。

using (OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\/Topology.accdb")) 
{ 
    con.Open(); 
    var trans = con.BeginTransaction(); 

    foreach (var pingReply in replies) 
    { 
     var status = ""; 
     if (pingReply.Reply.Status.ToString() == "Success") 
     { 
      online++; 
      status = "Online"; 
     } 
     else 
     { 
      status = "Offline"; 
      offline++; 
     } 

     string query = "UPDATE SystemStatus SET [email protected] WHERE IP='" + ipAddr + "'"; 

     OleDbCommand cmd = new OleDbCommand(query, con); 
     cmd.Transaction = trans; 
     cmd.Parameters.AddWithValue("@SystemStatus", status); 

     cmd.ExecuteNonQuery();   
    } 
    trans.Commit(); 
} 
+0

它引發一個錯誤:當分配給命令的連接處於未決的本地事務中時,ExcuteNonQuery需要命令執行事務。該命令的事務屬性尚未初始化。 –

+0

我的不好。在'新OleDbCommand' – jaket

+0

之後看到我的編輯線,或者只是把事務全部放在一起。我只是提供它作爲考慮事項。 – jaket