Запустите несколько процессов и дождитесь их завершения - PullRequest
0 голосов
/ 14 февраля 2019

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

Что должен делать мой код ?: У меня есть несколько ботов, работающих на виртуальных машинах / удаленных клиентах для имитации трафика, и я провожу некоторое исследование их поведения после манипулирования машиной, и это занимаетчасы до конца.Это делается на моей основной машине, которая использует инструменты ps для удаленного запуска сценариев на них.По сути, я запускаю один псекс, чтобы запустить мой бот, и псексе, который «следит» за выходом бота.До сих пор я использовал 4 программы, позволяющие запускать скрипт на 4 машинах, и одну программу, которая следила за этими 4 заданиями, если они закончили, поэтому он может отправить мне письмо, что задание выполнено, и если в нем есть ошибки или что-то подобноетот.И это раздражает - постоянно менять код в 4-х решениях ^^, поэтому я, хотя и мог заставить его работать асинхронно, но в классе мы говорили только о том, как что-то подобное может работать, и теперь я борюсь с различными концепциями.Нет, как это реализовать.Ниже я предоставил макет своего кода.

void mainClass(){
   doWithThreads(); // this works
   doWithTasks(); // this dosnt work
   doWithTaskAndWait(); // this works again
}

void doWithThreads(){
   Thread t1 = new Thread(() => startBot("Bot1"));
   t1.start();   
   Thread t2 = new Thread(() => startBot("Bot2"));
   t2.start();
   t1.join();
   t2.join();
   sendMail();
}

void async doWithTasks(){
   List<Task> tl = new List<Task>();
   tl.add(Task.Factory.Startnew(() => startBot("Bot3"));
   tl.add(Task.Factory.Startnew(() => startBot("Bot4"));
   await Task.WhenAll(tl); // jumps instantly to sendMail and Task in TL are never started
   sendMail();
}

void doWithTaskAndWait(){
   List<Task> tl = new List<Task>();
   tl.add(Task.Factory.Startnew(() => startBot("Bot5"));
   tl.add(Task.Factory.Startnew(() => startBot("Bot6"));
   Task.WhenAll(tl).Wait(); //I think this works bc its again busy waiting
   sendMail();
}

void startBot(string x){
   Process a = ... //pstoolsconfig
   Process check = ... //pstoolsconfig 
   a.start();
   check.start() // this one checks the logfile of process a
   while(!check.StandardError.ReadToEnd().Contains(x + " has finished")){
      check.start(); //should simulate busy waiting
      thread.sleep(1000) //wait a sec
   }//as soon it finds the phrases "BotX has finished" in the logfile it should be done with his job 

}

К сожалению, у меня нет никого, кого бы я мог спросить об этом, и я понятия не имею, почему метод async / await не работает.Моя идея состоит в том, что метод startBot возвращает void и bc этого, он никогда не сможет «подтвердить», что он завершил работу.И я думаю, что thread.join и task.whenall.wait похожи на занятые операции ожидания, которые блокируют все остальное в планировщике.Но, возможно, мне просто повезло, что эти методы очень быстро находят место в планировщике и выполняются «быстрее», чем sendmail.

Я надеюсь, что кто-то может помочь мне понять, что я делаю неправильно.

// Обновление 1: поведение doWithTask

List<Task> tl = new List<Task>();
tl.add(Task.Factory.Startnew(() => startBot("Bot3"));
Console.WriteLine(tl.elementat(0).status)); // running 
Task.WhenAll (tl).ContineWith(t => sendMail());
Console.WriteLine(tl.elementat(0).status)); // running
//end of code exe closed

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

Спасибо всем за помощь.Я понял это на выходных.

Я изменил дизайн из своего startBot, чтобы он возвращал Задачу, и затем ожидание сработало.

0 голосов
/ 14 февраля 2019

Давайте посмотрим, почему он работает так, как сейчас:

Thread.Join Doc

Блокируетвызывающий поток до тех пор, пока поток, представленный этим экземпляром, не завершится ...

Он ожидает завершения потоков (t1, t2), прежде чем продолжить с sendMail ().

Task.WhenAll Документ

Создает задачу, которая завершится после завершения всех поставленных задач.

Этане ждет.Создается еще одно задание, которое продолжается как обычно.

Task.WhenAll.Wait Doc

Ожидает завершения заданиявыполнение.

Это берет созданное выше задание и ожидает его завершения.( Task.WaitAll достиг бы того же)

Что вы можете сделать:

Если вы хотите заблокировать текущий поток до завершения:

Task.WaitAll(tl.ToArray());

Если вы не хотите заблокировать текущий поток:

Task.WhenAll(tl).ContinueWith(t => sendMail());

ContinueWith Создает продолжение, которое выполняется асинхроннокогда целевая задача завершена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...