2015-07-23 4 views
-1

Я работаю над программой, которая должна установить «n» множество SSH-соединений с удаленным сервером Linux и запускать команды времени для каждого соединения. «Операция, требующая много времени», в основном запускает скрипт, который настраивает Wireshark и слушает трафик.Остановка всех подключений SSH сразу

Для этого я использую библиотеку SharpSSH для C# и n много BackgroundWorkers в качестве потоков. Также для простоты приведенный ниже код имеет n = 2 потока BGW и SSH-соединения.

Код:

// runs when start is pressed 
    private void startButton_Click_1(object sender, EventArgs e) 
    { 
     sb = new StringBuilder(); 
     DateTime timeNow = DateTime.Now; 
     clickTime = timeNow.ToString("yyyyMMddhhmmssfff"); // store the exact time of the click 
     bw = bwArray[0]; 
     int index = 0; // ignore these 2 constants 

     foreach (BackgroundWorker bgw in bwArray) 
     { 
      if (bgw.IsBusy != true) 
      { 
       bgw.RunWorkerAsync(); 
       // runWorkerAsync for every BackgroundWorker in the array 
       //index++; 
      } 
     } 

    } 

// runWorkerAsync leads the BGWorker to this function 
    private void bw_doWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker worker = sender as BackgroundWorker; 

     if (worker.CancellationPending == true) 
     { 
      e.Cancel = true; 
     } 
     else 
     { 
      // let the UI know of button changes 
      int p = 0; 
      object param = "something"; // use this to pass any additional parameter back to the UI 
      worker.ReportProgress(p, param); 
      // UI notifying part ends here 

      // for the simplex case 
      if (numberOfConnections == 1) 
       startOperation(); 
      // for the multiplex case 
      else if (numberOfConnections > 1) 
      { 
       //while (p < numberOfConnections) 
       //{ 
        multiStartOperation(); 
       // p++; 
       //} 
      } 
      Thread.Sleep(500); 
     } 

    } 

// will be called for all ssh connections (in multiplex case) 
    private void multiStartOperation() 
    { 
     string[] command1Array = { "host2", "host2" }; 
     string[] command2Array = { clickTime + "_h2", clickTime + "_h2" }; 

     for (int index = 0; index < numberOfConnections; index++) 
     { 
      // shellArray is an array of SshExec objects 
      shellArray[index] = new SshExec(IPAddress, username, password); 
      try 
      { 
       shellArray[index].Connect(); 
      } 
      catch (JSchException se) 
      { 
       Console.Write(se.StackTrace); 
       System.Windows.Forms.MessageBox.Show("Couldn't connect to the specified port.", "Connection Error!"); 
      } 

      sb.Append(shellArray[index].RunCommand(command1Array[index]) + Environment.NewLine); 
      // first command is host3, or host4 etc. 

      // below is the time consuming command to run 
      string command = "./logcap.sh -c " + command2Array[index] + " -z"; 
      // sb is a global stringBuilder object, 
      // to which the command output is appended 
      sb.Append(shellArray[index].RunCommand(command)); 
     } 

    }  

Моя проблема заключается в следующем:

При нажатии на кнопку запуска на GUI, оба соединения должны начинаться и запустите сценарий. Принимая во внимание, что в приведенном выше коде, первый индекс shellArray (который состоит из объектов SshExec) подключается, подготавливает команды и запускает трудоемкую команду, после чего программа возвращается к пользовательскому интерфейсу, даже не запуская второе соединение. Это, очевидно, из-за цикла for, но я не мог понять, как это сделать.

Мне нужно, чтобы другой фоновый работник установил и запустил вторую команду со вторым сервером, так что, когда я нажимаю кнопку остановки в графическом интерфейсе, все соединения и потоки могут останавливаться вместе.

PS: Команды не останавливаются, если пользователь не нажимает кнопку остановки, которая посылает на сервер сигнал Ctrl-C.

Я относительно новичок во всех многопоточных и сетевых концепциях, поэтому, если есть какая-либо путаница или ошибка, сообщите мне.

Имейте славный день.

+0

1) Предположим, вы, по крайней мере, сказали нам, что вызов «RunWorkerAsync» вызывается («bgw.IsBusy' является ложным) во втором раунде. –

+0

2) Как вы инициализируете 'bwArray'? –

+0

3) Вы обновили бы название вопроса, чтобы описать фактическую проблему (= вы не можете запустить несколько фоновых работников/соединений)? –

ответ

0

Благодарим вас за ответы и приветствуем вас. :) Проблема действительно заключалась в невозможности одновременного запуска нескольких фоновых работников.

Мне удалось решить проблему. Оказывается, все, что мне нужно было выяснить, - как назначить фоновых работников SSH-соединениям. Чтобы сделать это, я создал класс следующим образом:

class BGW 
    { 
     private BackgroundWorker bgw; 
     private int index; 
     //getters, setters, constructors... 
    } 

После этого я преобразовал bwArray который был массив BackgroundWorkers в массив объектов BGW. При инициализации я присвоил каждому объекту BGW индекс.

Вместо того, чтобы иметь тупиковую петлю внутри multiStartOperation(), я отправил целочисленный параметр в multiStartOperation(), и эта функция использовала этот индекс для достижения выделенного фонового рабочего.

Пока это работает. Имейте славный день.

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