【问题标题】:Start multiple Processes and wait till they are finished启动多个进程并等待它们完成
【发布时间】:2019-02-18 18:19:58
【问题描述】:

我正在尝试启动多个任务,这将在远程机器上启动一个进程。在他们得出结论后,应该发送一封邮件。

我的代码应该做什么?:我在虚拟机/远程客户端上运行了多个机器人来模拟一些流量,并且我在操纵机器后对它们的行为进行了一些研究,这需要几个小时才能完成。这是由我的主机完成的,它使用 ps 工具在它们上远程运行脚本。基本上,我启动一个 psexe 来启动我的机器人,并启动一个 psexe 来“监视”机器人的输出。到目前为止,我使用 4 个程序让脚本在 4 台机器上运行,一个程序负责这 4 个任务(如果它们已完成),因此它可能会向我发送一封邮件,说明任务已完成,以及它是否有一些错误或类似的东西那。而且 tbh 总是在 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

【问题讨论】:

标签: c# process async-await


【解决方案1】:

让我们看看它为什么会像现在这样工作:

Thread.Join Doc

阻塞调用线程,直到此实例表示的线程终止...

它“等待”线程 (t1, t2) 在继续 sendMail() 之前终止。

Task.WhenAll Doc

创建一个将在所有提供的任务完成后完成的任务。

这个不等。它正在创建另一个任务并照常继续。

Task.WhenAll.Wait Doc

等待任务完成执行。

这个接受上面创建的任务并等待它的终止。 (Task.WaitAll 也会达到同样的效果)

你可以做什么:

如果你想阻塞当前线程直到完成:

Task.WaitAll(tl.ToArray());

如果你想阻塞当前线程:

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

ContinueWith 创建一个异步执行的延续 当目标任务完成时。

【讨论】:

  • 这是一个很好的答案,但对我没有帮助。我的问题是 startBot() 在到达代码末尾之前永远不会完成。例如: List tl = new List(); tl.add(Task.Factory.Startnew(() => startBot("Bot3")); Console.WriteLine(tl.elementat(0).status)); // 运行 Task.WhenAll(tl).ContineWith(t => sendMail()); Console.WriteLine(tl.elementat(0).status)); // 运行
  • @Kleisophabo 如果您想等待 startBot() 完成,您需要使用 Task.WaitAll(tl.ToArray()); sendMail(); Console.WriteLine(tl.elementat(0).status)); 或使用 ContinueWith Task.WhenAll(tl).ContinueWith(t =&gt; sendMail()).ContinueWith(t =&gt; Console.WriteLine(t.status))); 继续扩展
  • 如果这没有帮助你可能想要添加你的 startBot() 函数。也许它本身就是异步的?
  • 谢谢你的帮助,但这里的 startBot 和我的唯一不同是有很多字符串来定义启动 pstools 的参数。
【解决方案2】:

感谢大家的帮助。我在周末想通了。

我从我的 startBot 更改了设计,让它返回一个任务,然后 await 确实起作用了。

【讨论】:

    猜你喜欢
    • 2021-12-13
    • 1970-01-01
    • 2010-10-11
    • 2012-03-04
    • 1970-01-01
    • 2019-02-23
    • 1970-01-01
    • 2015-08-21
    • 2015-02-25
    相关资源
    最近更新 更多