.net中的命名管道(NamedPipe)

最近尝试代码分离,减少主程序中的代码,将很多Form都独立成单独的exe,主程序跟这些小程序间的通信就使用命名管道在进行。

之前运用过命名管道,但是是直接使用win32 api实现的,并且一直有问题,比如说有时候接收信息的阻塞被释放,但是又收不到任何东西。之前使用vs2005进行开发的,后来发现vs2010直接将命名管道封装成了类,就尝试使用了,发现比之前使用api时要顺手的多。

引用using System.IO.Pipes;这个命名空间,在vs2005中是没有此命名空间的,所以我将开发环境全部升级到了vs2010,还好升级比较方便。

我使用的情景都是阻塞式的,就是主程序调出某个exe后,主程序是无法运行的,必要等那个exe中程序执行完,或者关掉exe后,主程序才能响应。当然,如果需要做成非阻塞式的也是可以的,用线程或回调就行了。

vs2010自带的命名管道的类是分成服务器端跟客户端两个,有点类似使用soket的感觉,并且跟win32 api的方式也感觉不一样。win32 api的方式更像两边是对称的。

我封装了一个类,让软件调用的时候尽量的统一,不去区分服务器、客户端什么的。

下面是代码,注释写的应该也比较清楚。

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.IO.Pipes;
using System.Security.Principal;
using System.Threading;
using System.Diagnostics;

namespace pipe
{

    public class NamedPipe : IDisposable {

        string err = "";

        NamedPipeServerStream _pipeServer = null;
        NamedPipeClientStream _pipeClient = null;

        /// <summary>
        /// 初始化管道。每个进程发送与接收信息是两个管道进行通信。
        /// 两个进程使用的管道名是相对的
        /// 进程1使用的接收管道就是进程2使用的发送管道。进程2使用的发送管道就是进程1使用的接收管道。
        /// </summary>
        /// <param name="server">监听管道的名称</param>
        /// <param name="client">发送管道名称</param>
        public NamedPipe(string server, string client)
        {
            try {
                _pipeServer = new NamedPipeServerStream(server, PipeDirection.InOut, 10); 
                _pipeClient = new NamedPipeClientStream(".", client, PipeDirection.InOut);
            }
            catch (Exception ex) {
                err = ex.Message;
            }       
        }

        public bool openExe(string path) {
            Process p = new Process();

            try
            {
                p.StartInfo.FileName = path;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardInput = true;

                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardError = true;
                p.Start();
                return true;
            }
            catch (Exception ex)
            {
                err = ex.Message;
                return false;
            }
            finally { 
                p.Close();
                p.Dispose();
            }
        }

        /// <summary>
        /// 读取错误信息
        /// </summary>
        /// <returns></returns>
        public string Err() {
            string s;
            s = err;
            err = "";
            return s;        
        }
        
        /// <summary>
        /// 从管道中读取内容(阻塞式)
        /// </summary>
        /// <returns></returns>
        public string read()
        {
            try 
            {
                if (!_pipeServer.IsConnected)
                {
                    _pipeServer.WaitForConnection();
                }

                string str = "";
                StreamReader sr = new StreamReader(_pipeServer);
                while (_pipeServer.CanRead && (null != (str = sr.ReadLine())))
                {
                    Thread.Sleep(50);
                    return str;
                }
                return str;
            }
            catch (Exception ex)
            {
                err = ex.Message;
                return "";
            }      
        }

        /// <summary>
        /// 往管道中写入内容
        /// </summary>
        /// <param name="s">写入的内容</param>
        public bool send(string s)
        {
            try 
            {
                if (!_pipeClient.IsConnected)
                {
                    _pipeClient.Connect();
                }

                StreamWriter sw = new StreamWriter(_pipeClient);
                sw.WriteLine(s);
                sw.Flush();
                return true;
            }
            catch (Exception ex)
            {
                err = ex.Message;
                return false;
            }     
        }

        #region IDisposable 成员

        bool _disposed = false;
        public void Dispose()
        {          
            try 
            {
                if (!_disposed && _pipeServer != null)
                {
                    _pipeServer.Close();
                    _pipeServer.Dispose();
                }

                if (!_disposed && _pipeClient != null)
                {
                    _pipeClient.Close();
                    _pipeClient.Dispose();
                }

                _disposed = true;
            }
            catch (Exception ex)
            {
                err = ex.Message;
            }   
        }

        #endregion
    
    }

}

其实命名管道功能很强大,这里列举的只是在同一个电脑中两个进程间的通信,它甚至可以实现网络间的进程的通信,功能强大带来的开销以及效率肯定就是不太友好的,下一步准备来看看匿名管道,可能会更加符合我的应用场景。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值