gpt4 book ai didi

c# - 使用控制台应用程序 .NET Core 在 C# 中并行运行两个 dotnet 进程

转载 作者:太空宇宙 更新时间:2023-11-03 14:47:50 25 4
gpt4 key购买 nike

我有一个包含三个控制台的项目。一个控制台将并行打开其他两个进程来执行一些工作(独立)。

所有控制台都使用 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();
}
}
}

ConsoleNumberOneConsoleNumberTwo 看起来很相似

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 端实现?

最佳答案

无需使用 Task.Run 来启动子进程。 documentation suggests 不是使用 WaitForExit(); 来阻塞直到进程退出:

To avoid blocking the current thread, use the Exited event.

在任务之前,事件是异步执行作业和接收通知的方法之一。这称为基于事件的异步模式。可以使用 TaskCompletionSource 将事件转换为任务。这在 How to: Wrap EAP Patterns in a Task 中有描述。 .

这个例子比它应该的更冗长。在这种情况下,将 Exited 转换为 Task 很简单:

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可用于将任务设置为故障状态,在等待时引发异常。例如,如果任何进程返回非零退出代码,这可以用于取消等待

关于c# - 使用控制台应用程序 .NET Core 在 C# 中并行运行两个 dotnet 进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53316087/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com