从一个C#控制台应用程序发送消息到另一个应用程序

6
首先,我已经阅读了所有相关主题,它们提供了一般的想法,但实现对我不起作用:
将字符串从一个控制台应用程序发送到另一个
如何以用户键入的方式向控制台发送输入?
从控制台应用程序发送输入/获取输出 (C#/WinForms)
我有一个控制台应用程序,在取消请求之前在后台执行某些操作。 典型的使用场景是:
1)执行应用程序
2)输入数据
3)发出启动命令
4)一段时间后,输入停止命令
5)退出应用程序
子应用程序Program.cs
static void Main()
{
    Console.WriteLine("Enter input parameter : ");
    var inputParameter = Console.ReadLine();
    Console.WriteLine("Entered : " + inputParameter);

    var tokenSource = new CancellationTokenSource();
    var token = tokenSource.Token;
    Task.Factory.StartNew(() =>
        {
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("Stopping actions");
                    return;
                }
                // Simulating some actions
                Console.Write("*");
            }
        }, token);
    if (Console.ReadKey().KeyChar == 'c')
    {
        tokenSource.Cancel();
        Console.WriteLine("Stop command");
    }
    Console.WriteLine("Finished");
    Console.ReadLine();
}

我需要的是某种主机工具来控制这个应用程序——在每个实例上产生多个实例并执行所需的用户操作。 主机应用程序Program.cs:
static void Main()
{
    const string exe = "Child.exe";
    var exePath = System.IO.Path.GetFullPath(exe);
    var startInfo = new ProcessStartInfo(exePath)
    {
        RedirectStandardOutput = true,
        RedirectStandardInput = true,
        WindowStyle = ProcessWindowStyle.Hidden,
        WindowStyle = ProcessWindowStyle.Maximized,
        CreateNoWindow = true,
        UseShellExecute = false
    };

    var childProcess = new Process { StartInfo = startInfo };
    childProcess.OutputDataReceived += readProcess_OutputDataReceived;
    childProcess.Start();
    childProcess.BeginOutputReadLine();
    Console.WriteLine("Waiting 5s for child process to start...");
    Thread.Sleep(5000);

    Console.WriteLine("Enter input");
    var msg = Console.ReadLine();
    // Sending input parameter
    childProcess.StandardInput.WriteLine(msg);
    // Sending start command aka any key
    childProcess.StandardInput.Write("s");
    // Wait 5s while child application is working
    Thread.Sleep(5000);
    // Issue stop command
    childProcess.StandardInput.Write("c");
    // Wait for child application to stop
    Thread.Sleep(20000);
    childProcess.WaitForExit();
    Console.WriteLine("Batch finished");    
    Console.ReadLine();
}

当我运行这个工具时,在第一次输入后,它会崩溃并显示“已停止工作”错误,并提示将内存转储发送给Microsoft。在VS中的输出窗口没有显示异常。
猜测此问题发生在应用程序之间,可能是由于输出流缓冲区溢出(子应用程序每秒钟写入了大量星号,模拟了可能很大的实际输出),我还不知道如何解决。我不需要将子进程的输出传递给主机(只需要向子进程发送启动-停止命令),但注释掉RedirectStandardOutput和OutputDataReceived并不能解决这个问题。有什么好的想法吗?

为什么不使用IPC和管道?如果要在单个客户端或LAN内工作,这非常容易。WCF是另一个选择。 - Alireza
我需要从一个应用程序传递3个字符串到另一个应用程序。尽可能保持简单。 - Jaded
通常启动许多进程来完成工作并没有太大的意义。通过启动许多线程,您将实现完全相同的事情。这样做有许多优点,包括在出现问题时获得更好的诊断。 - Hans Passant
无论你想要传达什么,这都没有关系。推荐阅读:http://msdn.microsoft.com/en-us/library/bb546085.aspx 和 https://dev59.com/ZmYr5IYBdhLWcg3wRoSW - Alireza
@HansPassant 嗯,每个子应用程序每分钟发出约1000个服务请求(平均同时20个),内存消耗是一个问题(OutOfMemory)。考虑到使用标准的WCF和SoapHttpClientProtocol包装器,优化的空间不多。 - Jaded
使用单独的进程而不是线程有很好的优点,例如当您想要避免在风险非常真实的环境中(32位进程和/或旧版本的CLR)由大对象堆碎片化引起的内存不足异常时。 - jhexp
3个回答

10

我建议使用NamedPipeServerStreamNamedPipeClientStream,它们允许您打开一个流,在给定的机器上在进程之间进行通信。

首先,这将创建一个管道服务器流,并等待某人连接:

    var stream = new NamedPipeServerStream(this.PipeName, PipeDirection.InOut);
    stream.WaitForConnection();
    return stream;

接下来,这将连接到那个流(来自您的其他进程),允许您在任何方向上进行读/写操作:

    var stream = new NamedPipeClientStream(".", this.PipeName, PipeDirection.InOut);
    stream.Connect(100);
    return stream;

0

另一个选择是使用MSMQ,你可以在这里找到一个好的教程。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接