[英]Run two dotnet processes in parallel C# with Console app .NET Core
我有一個帶有三個控制台的項目。 一個控制台將並行打開另兩個進程來獨立完成一些工作。
所有控制台都使用dotnet核心框架。
MultipleConsoleWindows
是主要應用程序,如下所示:
static void Main(string[] args)
{
Task t1 = new Task(async () => { await ProcessManager.StartAsync("c1"); });
Task t2 = new Task(async () => { await ProcessManager.StartAsync("c2"); });
// what should do here ?
Console.WriteLine("done");
Console.Read();
}
和ProcessManager類:
public static class ProcessManager
{
const string C1 = @"pathTo\ConsoleNumberOne.dll";
const string C2 = @"pathTo\ConsoleNumberTwo.dll";
public static async Task<string> StartAsync(string type)
{
Console.WriteLine($"Start {type}");
var proc = type.Equals("c1") ? C1 : C2;
return await Task.Run(() => StartProcess(proc));
}
static string StartProcess(string proc)
{
ProcessStartInfo procStartInfo = new ProcessStartInfo();
procStartInfo.FileName = "dotnet";
procStartInfo.Arguments = $"\"{proc}\"";
procStartInfo.WorkingDirectory = Path.GetDirectoryName(proc);
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardError = true;
int output = 0;
StringBuilder sb = new StringBuilder();
using (Process pr = new Process())
{
pr.StartInfo = procStartInfo;
pr.OutputDataReceived += (s, ev) =>
{
if (string.IsNullOrWhiteSpace(ev.Data))
{
return;
}
sb.AppendLine(ev.Data);
string[] split = ev.Data.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
int.TryParse(split[split.Length - 1], out output);
};
pr.ErrorDataReceived += (s, err) =>
{
if (!string.IsNullOrWhiteSpace(err.Data))
{
sb.AppendLine(err.Data);
output = 0;
}
};
pr.EnableRaisingEvents = true;
pr.Start();
pr.BeginOutputReadLine();
pr.BeginErrorReadLine();
pr.WaitForExit();
return sb.ToString();
}
}
}
ConsoleNumberOne
和ConsoleNumberTwo
看起來相似
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Thread.Sleep(10000);
}
和
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Thread.Sleep(5000);
}
我正在嘗試同時打開兩個自己工作的控制台。
如何在MultipleConsoleWindows
端實現呢?
Maebe這可以解決問題
static void Main(string[] args)
{
Action t1 = new Action(async () => { await ProcessManager.StartAsync("c1"); });
Action t2 = new Action(async () => { await ProcessManager.StartAsync("c2"); });
Parallel.Invoke(t1, t2);
Console.WriteLine("done");
Console.Read();
}
無需使用Task.Run
啟動子進程。 而不是使用WaitForExit();
文檔建議 :在進程退出之前進行阻塞:
為避免阻塞當前線程,請使用Exited事件。
在執行任務之前,事件是異步執行作業和接收通知的方法之一。 這稱為Event-Based Asynchronous Pattern
。 可以使用TaskCompletionSource將事件轉換為Tasks。 如何:在任務中包裝EAP模式中對此進行了描述。
該示例比應有的更為冗長。 在這種情況下, Exited
到任務的convertint很簡單:
static Task<string> StartProcess(string proc)
{
StringBuilder sb = new StringBuilder();
Process pr = new Process
{
StartInfo = procStartInfo
};
var tcs = new TaskCompletionSource<string>();
pr.Exited += (o, e) =>
{
tcs.SetResult(sb.ToString());
pr.Dispose();
};
....
return tcs.Task;
}
這樣可以啟動並等待多個進程:
static async Task Main(string[] args)
{
var p1 = StartProcess("--version");
var p2 = StartProcess("--list-runtimes");
string[] responses=await Task.WhenAll(p1, p2);
...
}
TaskCompletionSource.SetResult完成tcs返回的任務並設置其結果,在這種情況下為字符串。 SetException可用於將任務設置為故障狀態,從而在等待時引發異常。 例如,這可以用於取消任何進程返回非零退出代碼的等待
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.