2015-08-17 42 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