进程间通信示例服务器&客户C#

时间:2016-02-08 21:36:13

标签: c# wpf ipc

使用.NET 4,wpf c#,我在两个进程之间传递方法返回值和参数。

由于我需要连接打开并始终处于活动状态,所以我尽力减少重复出现的代码(在循环内),但除非我把整个代码放在循环中但它没有成功(在第一次之后)转移连接到服务器已关闭),因为它在这里,它确实重复工作。

我想知道它首先是应该编码的方式,所有过程包括新实例,处理,关闭......在循环中?

进程间通信唯一可用的数据类型是否以字符串形式传递(效率低下)?

public void client()
{
    for (int i = 0; i < 2; i++)
    {
        System.IO.Pipes.NamedPipeClientStream pipeClient = 
            new System.IO.Pipes.NamedPipeClientStream(".", "testpipe", 
                          System.IO.Pipes.PipeDirection.InOut, System.IO.Pipes.PipeOptions.None);

        if (pipeClient.IsConnected != true) 
        {
            pipeClient.Connect(550); 
        }

        System.IO.StreamReader sr = new System.IO.StreamReader(pipeClient);
        System.IO.StreamWriter sw = new System.IO.StreamWriter(pipeClient);

        string status;
        status = sr.ReadLine();

        if (status == "Waiting")
        {
           try
           {
              sw.WriteLine("param1fileName.cs,33" + i);
              sw.Flush();
              pipeClient.Close();
           }
           catch (Exception ex) { throw ex; }
        }
    }
}


public string server()
{
    NamedPipeServerStream pipeServer = null;
    do
    {
        try
        {
            pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 4);

            StreamReader sr = new StreamReader(pipeServer);
            StreamWriter sw = new StreamWriter(pipeServer);

            System.Threading.Thread.Sleep(100);
            pipeServer.WaitForConnection();
            string test;
            sw.WriteLine("Waiting");
            sw.Flush();
            pipeServer.WaitForPipeDrain();
            test = sr.ReadLine();
            if (!string.IsNullOrEmpty(test))
                try
                {
                    System.Windows.Application.Current.Dispatcher.Invoke(new Action(() => MbxTw.Show(Convert.ToInt32(test.Split(',')[1]), test.Split(',')[0], "method()", "Warning!! - " + "content")), System.Windows.Threading.DispatcherPriority.Normal);
                }
                catch (Exception e)
                {
                }
        }

        catch (Exception ex) { 
            throw ex; }

        finally
        {
            pipeServer.WaitForPipeDrain();
            if (pipeServer.IsConnected) { pipeServer.Disconnect(); }
        }
    } while (true);
}

1 个答案:

答案 0 :(得分:0)

在对进程间通信进行彻底研究之后,我已经改变了使用命名管道到内存映射文件的方法, 因为它是所有轮次的赢家,不需要重新创建它并且更快

我提出了最终的分区全局应用程序进程间通信

对代码的任何想法将不胜感激!

public class MMFinterComT
{
    public EventWaitHandle flagCaller1, flagCaller2, flagReciver1, flagReciver2;

    private System.IO.MemoryMappedFiles.MemoryMappedFile mmf;
    private System.IO.MemoryMappedFiles.MemoryMappedViewAccessor accessor;

    public virtual string DepositChlName { get; set; }
    public virtual string DepositThrdName { get; set; }
    public virtual int DepositSize { get; set; }
    private System.Threading.Thread writerThread;
    private bool writerThreadRunning;


    public int ReadPosition { get; set; }
    public List<string> statusSet;
    private int writePosition;
    public int WritePosition
    {
        get { return writePosition; }
        set
        {
            if (value != writePosition)
            {
                this.writePosition = value;
                this.accessor.Write(WritePosition + READ_CONFIRM_OFFSET, true);
            }
        }
    }

    private List<byte[]> dataToSend;

    private const int DATA_AVAILABLE_OFFSET = 0;
    private const int READ_CONFIRM_OFFSET = DATA_AVAILABLE_OFFSET + 1;
    private const int DATA_LENGTH_OFFSET = READ_CONFIRM_OFFSET + 1;
    private const int DATA_OFFSET = DATA_LENGTH_OFFSET + 10;
    public IpcMMFinterComSF.MMFinterComTStatus IntercomStatus;
    public MMFinterComT(string ctrIpcChannelNameStr, string ctrIpcThreadName, int ctrMMFSize)
    {
        this.DepositChlName = ctrIpcChannelNameStr;
        this.Deposit Size = ctrMMFSize;
        this.DepositThrdName = ctrIpcThreadName;
        mmf = MemoryMappedFile.CreateOrOpen(DepositChlName, DepositSize);
        accessor = mmf.CreateViewAccessor(0, DepositSize, System.IO.MemoryMappedFiles.MemoryMappedFileAccess.ReadWrite);//if (started)
        //smLock = new System.Threading.Mutex(true, IpcMutxName, out locked);
        ReadPosition = -1;
        writePosition = -1;
        this.dataToSend = new List<byte[]>();
        this.statusSet = new List<string>();
    }
    public bool reading;
    public byte[] ReadData;
    public void StartReader()
    {
        if (this.IntercomStatus != IpcMMFinterComSF.MMFinterComTStatus._Null || ReadPosition < 0 || writePosition < 0)
            return;
        this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus.PreparingReader;

        System.Threading.Thread t = new System.Threading.Thread(ReaderThread);
        t.IsBackground = true;
        t.Start();

    }
    private void ReaderThread(object stateInfo)
    {

            // Checks if there is something to read.
        this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus.TryingToRead;
            this.reading = accessor.ReadBoolean(ReadPosition + DATA_AVAILABLE_OFFSET);
            if (this.reading)
            {
                this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus.ReadingData;
                // Checks how many bytes to read.
                int availableBytes = accessor.ReadInt32(ReadPosition + DATA_LENGTH_OFFSET);
                this.ReadData = new byte[availableBytes];
                // Reads the byte array.
                int read = accessor.ReadArray<byte>(ReadPosition + DATA_OFFSET, this.ReadData, 0, availableBytes);

                // Sets the flag used to signal that there aren't available data anymore.
                accessor.Write(ReadPosition + DATA_AVAILABLE_OFFSET, false);
                // Sets the flag used to signal that data has been read. 
                accessor.Write(ReadPosition + READ_CONFIRM_OFFSET, true);
                this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus.FinishedReading;
            }
            else this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus._Null;

    }

    public void Write(byte[] data)
    {
        if (ReadPosition < 0 || writePosition < 0)
            throw new ArgumentException();
        this.statusSet.Add("ReadWrite:-> " + ReadPosition + "-" + writePosition);



        lock (this.dataToSend)
            this.dataToSend.Add(data);

        if (!writerThreadRunning)
        {
            writerThreadRunning = true;
            writerThread = new System.Threading.Thread(WriterThread);
            writerThread.IsBackground = true;
            writerThread.Name = this.DepositThrdName;
            writerThread.Start();
        }
    }
    public void WriterThread(object stateInfo)
    {
        while (dataToSend.Count > 0 && !this.disposed)
        {
            byte[] data = null;
            lock (dataToSend)
            {
                data = dataToSend[0];
                dataToSend.RemoveAt(0);
            }

            while (!this.accessor.ReadBoolean(WritePosition + READ_CONFIRM_OFFSET))
                System.Threading.Thread.Sleep(133);

            // Sets length and write data.
            this.accessor.Write(writePosition + DATA_LENGTH_OFFSET, data.Length);
            this.accessor.WriteArray<byte>(writePosition + DATA_OFFSET, data, 0, data.Length);

            // Resets the flag used to signal that data has been read.
            this.accessor.Write(writePosition + READ_CONFIRM_OFFSET, false);
            // Sets the flag used to signal that there are data avaibla.
            this.accessor.Write(writePosition + DATA_AVAILABLE_OFFSET, true);
        }

        writerThreadRunning = false;
    }



    public virtual void Close()
    {

        if (accessor != null)
        {
            try
            {
                accessor.Dispose();
                accessor = null;
            }
            catch { }
        }

        if (this.mmf != null)
        {
            try
            {
                mmf.Dispose();
                mmf = null;
            }
            catch { }
        }

        disposed = true;
        GC.SuppressFinalize(this);
    }
    private bool disposed;

}

和用法

instaciant一次!

public static bool StartCurProjInterCom(IpcAccessorSetting curSrv, int DepoSize)
{
    if(CurProjMMF ==null)
    CurProjMMF = new MMFinterComT(curSrv.Channel.ToString(), curSrv.AccThreadName.ToString(), DepoSize);
    CurProjMMF.flagCaller1 = new EventWaitHandle(false, EventResetMode.ManualReset, CurProjMMF.DepositThrdName);
    CurProjMMF.flagCaller2 = new EventWaitHandle(false, EventResetMode.ManualReset, CurProjMMF.DepositThrdName);
    CurProjMMF.flagReciver1 = new EventWaitHandle(false, EventResetMode.ManualReset, IpcAccessorThreadNameS.DebuggerThrd.ToString());

    CurProjMMF.ReadPosition = curSrv.AccessorSectorsSets.DepoSects.Setter.Read;
    CurProjMMF.WritePosition = curSrv.AccessorSectorsSets.DepoSects.Setter.Write;
    Console.WriteLine("MMFInterComSetter.ReadPosition " + CurProjMMF.ReadPosition);
    Console.WriteLine("MMFInterComSetter.WritePosition " + CurProjMMF.WritePosition);

    CurProjMMF.StartReader();

    return true;
}

使用很多

 public static void StartADebugerInterComCall(IpcCarier SetterDataObj)
{
    IpcAccessorSetting curSrv = new IpcAccessorSetting(IpcMMf.IPChannelS.Debugger, IpcAccessorThreadNameS.DebuggerThrdCurProj, 0, 5000);
    StartCurProjInterCom(curSrv, 10000);

    var dataW = SetterDataObj.IpcCarierToByteArray();//System.Text.Encoding.UTF8.GetBytes(msg);
    CurProjMMF.Write(dataW);
    CurProjMMF.flagReciver1.Set();
    CurProjMMF.flagCaller1.WaitOne();
    CurProjMMF.flagCaller1.Reset();
}