2015-08-17 3 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(); 
    } 

задача Ping

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 из списка и вставляю его в DB. –

ответ

1

Это не мой ар но я предполагаю, что на создание новой 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

Смежные вопросы