zoukankan      html  css  js  c++  java
  • 【.net 深呼吸】通过标准输入/输出流来完成进程间通信

    实现进程之间煲电话粥的方式,有好几种,比如,你可以用这些方案:

    1、使用socket来传递。这个好像很无聊,本地进程之间也用socket?不过,通过本机回环网络确实可以进程之间通信。

    2、WCF,与上面的相似,也是利用本机回环地址来在进程间通信。

    3、内存映射文件。这个可能有些朋友不太熟,毕竟平时装逼时也装不上这个。内存映射文件类似于磁盘中的物理文件,只不过它是存在于内存中的,一旦引用文件的最后一个进程退出,内存映射文件就会释放。多个进程间可以共享内存映文件来分享银行卡上的钱。

    本文老周还介绍第 4 种方案——通过标准的输入/输出流来读写。输入流是向一个进程写入数据,相反地,输出流就是从某个进程读取数据。

    原理不复杂,实现起来也不难,只需要用到一个我们都很熟悉的类:Console,这个类不仅可以在控制台应用程序中输入/输出文本,也可以用于标准流。

    好,老周用一个例子来说明一下。

    这个例子是这样的,假设有一个可执行文件,它没有UI,只是用于安装,在安装过程中,它会实时输出安装进度。然后,有另外一个程序,有窗口,这个程序会调用前面那个程序进行安装,并实时读出安装进度,显示到进度条控件上。

    首先实现第一个程序,无窗口无UI无房无车,纯屌丝一个。

        class MainClass
        {
            static void Main()
            {
                BinaryWriter writer = new BinaryWriter(Console.OpenStandardOutput());
                byte p = 0;
                do
                {
                    writer.Write(p);
                    Thread.Sleep(50);
                    p++;
                }
                while (p <= 100);
                writer.Close();
            }
        }

    获取标准流,可以调用 OpenStandardOutput,或OpenStandardInput,这两个方法返回的流对象,可以灵活操作。还可以访问 Out / In 属性来获取标准流,它返回的是 TextReader 或 TextWriter,这用于读写文本较方便。

    此处,老周只考虑写一个数值(0 - 100),所以,用 BinaryWriter 类操作会快乐一点。

    这个项目,你既能生成为控制台应用程序,也可以是Windows应用程序,只要是.exe即可。

    随后,我们实现有窗口有UI有房有车,纯壕一个。

                string exePath = @"......SampleAppinDebugSampleApp.exe";
                IProgress<int> prgs = new Progress<int>(p =>
                 {
                     progressBar1.Value = p;
                 });
    
                ……
                await Task.Run(() =>
                {
                    ProcessStartInfo start = new ProcessStartInfo();
                    start.FileName = exePath; //要执行的.exe文件
                    start.CreateNoWindow = true; //无窗口
                    start.UseShellExecute = false; //非Shell行为
                    start.RedirectStandardOutput = true; //必须,否则连毛都不出来
                    Process p = Process.Start(start);
                    BinaryReader reader = new BinaryReader(p.StandardOutput.BaseStream);
                    while (true)
                    {
                        byte prs = reader.ReadByte();
                        prgs.Report(prs);
                        if (prs == 100) break;
                    }
                    reader.Close();
                    p.WaitForExit();
                    p.Close();
                });
                ……

    IProgress<T>是个好东西,它的实现类是 Progress<T>,只要我们在UI线程上把它实例化(即它的实例属于UI线程),那么在跨线程报告进度时会简便很多。实例化时,传一个Action<T>委托实例,用来回调进度。

    启动进程前要准备一个 ProcessStartInfo,它可以设置一些参数。

    如:

                    ProcessStartInfo start = new ProcessStartInfo();
                    start.FileName = exePath; //要执行的.exe文件
                    start.CreateNoWindow = true; //无窗口
                    start.UseShellExecute = false; //非Shell行为
                    start.RedirectStandardOutput = true; //必须,否则连毛都不出来

    反正安装程序是没有UI的,就让CreateNoWindow为真,不创建主窗口。另外,RedirectStandardOutput属性必须为真,不然我们代码就无法访问输入/输出流,只有重定向后的标准流才能在代码中使用。

    运行结果如下图所示。

     当然,你也可以用标准流来读写文本,或其他数据,这里读写数值,只作演示。

    示例代码下载地址

  • 相关阅读:
    Time Zone 【模拟时区转换】(HDU暑假2018多校第一场)
    HDU 1281 棋盘游戏 【二分图最大匹配】
    Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
    Codeforces Round #527 (Div. 3) D2. Great Vova Wall (Version 2) 【思维】
    Codeforces Round #527 (Div. 3) D1. Great Vova Wall (Version 1) 【思维】
    Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round 4) C. Connect Three 【模拟】
    Avito Cool Challenge 2018 E. Missing Numbers 【枚举】
    Avito Cool Challenge 2018 C. Colorful Bricks 【排列组合】
    005 如何分析问题框架
    004 如何定义和澄清问题
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/6905285.html
Copyright © 2011-2022 走看看