简体   繁体   English

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

[英]Run two dotnet processes in parallel C# with Console app .NET Core

I have a project with three consoles. 我有一个带有三个控制台的项目。 One console will open in parallel other two processes to do some jobs (independently). 一个控制台将并行打开另两个进程来独立完成一些工作。

All consoles are using dotnet core framework. 所有控制台都使用dotnet核心框架。

MultipleConsoleWindows is main application which looks like: 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();
}

and ProcessManager class: 和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();
        }
    }
}

The ConsoleNumberOne and ConsoleNumberTwo look similar ConsoleNumberOneConsoleNumberTwo看起来相似

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");
    Thread.Sleep(10000);
}

and

static void Main(string[] args)
{
     Console.WriteLine("Hello World!");
     Thread.Sleep(5000);
}

I'm trying to open two consoles in same time which do own job. 我正在尝试同时打开两个自己工作的控制台。

How to achieve that in MultipleConsoleWindows side ? 如何在MultipleConsoleWindows端实现呢?

Maebe this can do the trick 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();
}

There's no need to use Task.Run to start a child process. 无需使用Task.Run启动子进程。 Instead of using WaitForExit(); 而不是使用WaitForExit(); to block until the process exits, the documentation suggests : 文档建议 :在进程退出之前进行阻塞:

To avoid blocking the current thread, use the Exited event. 为避免阻塞当前线程,请使用Exited事件。

Before tasks, events were one of the methods of executing jobs asynchronously and receiving notifications. 在执行任务之前,事件是异步执行作业和接收通知的方法之一。 This is called the Event-Based Asynchronous Pattern . 这称为Event-Based Asynchronous Pattern Events can be converted to Tasks using a TaskCompletionSource. 可以使用TaskCompletionSource将事件转换为Tasks。 This is described in How to: Wrap EAP Patterns in a Task . 如何:在任务中包装EAP模式中对此进行了描述。

The example is a bit more verbose than it should. 该示例比应有的更为冗长。 In this case, convertint Exited to a Task is straightforward : 在这种情况下, 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;
}

Multiple processes can be started and awaited this way : 这样可以启动并等待多个进程:

static async Task Main(string[] args)
{
    var p1 = StartProcess("--version");
    var p2 = StartProcess("--list-runtimes");

    string[] responses=await Task.WhenAll(p1, p2);

    ...
}

TaskCompletionSource.SetResult completes the task returned by the tcs and sets its result, in this case a string. TaskCompletionSource.SetResult完成tcs返回的任务并设置其结果,在这种情况下为字符串。 SetException can be used to set the task to the faulted state, raising an exception when awaited. SetException可用于将任务设置为故障状态,从而在等待时引发异常。 This could be used for example to cancel awaiting if any of the processes returned a non-zero exit code 例如,这可以用于取消任何进程返回非零退出代码的等待

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 dotnet run 时如何调试 .NET 核心控制台应用程序 - How to Debug a .NET Core Console App When Using dotnet run 在c#dotnet核心控制台应用程序中保护密码输入 - Securing a password input in c# dotnet core console app XML 在 XmlSerializer 上返回 NULL 反序列化 DotNet 核心 C#(控制台应用程序) - XML returns NULL on XmlSerializer Deserialize DotNet Core C# (Console App) 如何针对dotnet核心控制台应用程序运行验收测试? - How to run acceptance test against dotnet core console app? 在 .NET Core C# 控制台应用程序中使用 HttpClient 进行 Google 社交登录? - Google social login with HttpClient in .NET Core C# console app? Visual Studio C#控制台应用程序(.NET Core)模板不同 - Visual Studio C# Console App (.NET Core) Template Different 在 .NET Core 控制台应用程序 C# 中播放音频 - Playing Audio in .NET Core Console App C# C# Do.net 核心控制台 appsettings.json 运行时重新加载 - C# Dotnet core Console appsettings.json runtime reload 无法在 Linux 上运行 C# 控制台应用程序 .net 6.0) - Fail to run C# console app (net 6.0) on Linux ASP.Net Core应用程序可在Visual Studio中运行,但不能与dotnet运行 - ASP.Net Core app works in visual studio but not with dotnet run
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM