【.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 = @"..\..\..\SampleApp\bin\Debug\SampleApp.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屬性必須為真,不然我們代碼就無法訪問輸入/輸出流,只有重定向后的標准流才能在代碼中使用。

 

運行結果如下圖所示。

 

 當然,你也可以用標准流來讀寫文本,或其他數據,這里讀寫數值,只作演示。

示例代碼下載地址

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM