尝试从NamedPipeClientStream写入NamedPipeServerStream

时间:2019-08-17 11:20:07

标签: c# named-pipes broken-pipe

我有一个程序,该程序必须与从第一个调用的另一个程序通信。 我设法使用NamedPipes将所需的数据从第一个程序发送到第二个程序。 当第二个程序关闭时,我需要将一些数据发送回第一个程序。我在第一个程序中设置了NamedPipeServerStream,从第二个程序的Closing事件中设置了NamedPipeClientStream。现在,当我尝试从ClientStream写入内容时,出现了管道破裂的错误。

这是第一个程序中的代码:

private void CreateOverlay(object sender, EventArgs e)
    {
        if (oinstallfolder != null)
        {
            string processfilename = oinstallfolder.ToString() + "\\SecondProgram.exe";*/

        string processfilename = "SecondProgram.exe";

        if (File.Exists(processfilename))
            {

                foreach (Process clsProcess in Process.GetProcesses())
                {
                    if (clsProcess.ProcessName.Equals("SecondProgram"))
                    {
                        this.threadHandleOverlayBounds = new Thread(new ThreadStart(this.ExchangeMapOverlayBoundsServer));
                        this.threadHandleOverlayBounds.Start();
                        this.threadHandleOverlayFile = new Thread(new ThreadStart(this.ExchangeMapOverlayFileServer));
                        this.threadHandleOverlayFile.Start();
                        ShowWindow(clsProcess.MainWindowHandle, SW_SHOWNORMAL);
                        SetForegroundWindow(clsProcess.MainWindowHandle);
                        return;
                    }
                }
            try
            {
                this.threadHandleOverlayBounds = new Thread(new ThreadStart(this.ExchangeMapOverlayBoundsServer));
                this.threadHandleOverlayBounds.Start();
                Logger.Logger.Write("Log.txt", "Starting Filethread serverside");

                this.threadHandleOverlayFile = new Thread(new ThreadStart(this.ExchangeMapOverlayFileServer));
                this.threadHandleOverlayFile.Start();

                Process.Start(processfilename);
            }
            catch { }

            }
        }
    }


 private void ExchangeMapOverlayFileServer()
        {
            try
            {
                using (NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("OverlayFilePipe", PipeDirection.In, 1, PipeTransmissionMode.Byte))
                {
                    string line;
                    namedPipeServer.WaitForConnection();
                    StreamReader sr = new StreamReader(namedPipeServer);
                    line = sr.ReadLine();
                    namedPipeServer.Disconnect();
                    namedPipeServer.Close();
                }
            }
            catch(Exception e)
            {
                Logger.Logger.Write("OverlayGenerator.txt", "namedPipeServer exception: " + e.Message + "\n" + e.StackTrace);
            }

        }

这是第二个程序中的代码

this.Closing += (s, a) =>
        {
            Logger.Logger.Write("Log.txt", "Window Closing");
            this.threadHandleOverlayFile = new Thread(new ThreadStart(this.HandleWindowClosing));
            this.threadHandleOverlayFile.Start();
            while (!done)
            {
                Thread.Sleep(100);
            }

        };


  private void HandleWindowClosing()
    {
        if (!String.IsNullOrEmpty(this.latestSavedOverlayPath))
        {
            try
            {
                using (NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "OverlayFilePipe", PipeDirection.Out))
                {
                    namedPipeClient.Connect();
                    StreamWriter sw = new StreamWriter(namedPipeClient);
                    sw.AutoFlush = true;
                    sw.WriteLine("testphrase");
                    namedPipeClient.Close();
                    this.done = true;
                }

            }
            catch (Exception e) { Logger.Logger.Write("OverlayGenerator.txt", "Exception in Client: " + e.Message + "\n" + e.StackTrace); }
        }
        else
        {
            Logger.Logger.Write("OverlayGenerator.txt", "Latest saved OverlayPath = " + this.latestSavedOverlayPath);
        }
    }

我尝试使用Autoflush = true进行此操作,而没有使用。有了它,我在行

处遇到了管道破裂的异常
sw.WriteLine("testphrase");

没有它,客户端只会运行到最后,什么也没发生。

我的错误在哪里? 谢谢。

编辑

好的,我就是不明白。我编写了一个测试程序,该程序的构建方式与实际程序相同。两个应用程序,第一个启动第二个。我在第一个应用程序中的线程中启动管道服务器,在第二个应用程序中的客户端中启动线程。唯一的区别是,我在调试模式下运行此测试项目,而我无法对实际程序执行此操作。现在,在测试程序中,这件事非常简单并且可以解决。当我在实际程序中使用完全相同的方法时,它不起作用。 在测试程序中,我需要在streamwriter上使用flush,并且不会出现异常。线程的同步由管道本身处理,如果我正确理解的话应该如此。

大师看起来像这样:

private const string CLIENTPROC = "C:\\Users\\Maik\\Source\\Repos\\PipeTest\\PipeClient\\obj\\x86\\Release\\PipeClient.exe";
        private ManualResetEvent threadResetEvent;
        private Thread threadHandlePipeSendLast;
        private Process procClient;
        private string msgPipeSend;
        private volatile bool bMsgPipeSend;
        public MainWindow()
        {
            InitializeComponent();
            this.threadResetEvent = new ManualResetEvent(false);
            System.Diagnostics.Debug.WriteLine("### starting thread");
            this.threadHandlePipeSendLast = new Thread(new ThreadStart(this.ExchangeMapOverlayFileServer));
            this.threadHandlePipeSendLast.Start();
        }

        private void ExchangeMapOverlayFileServer()
        {
            System.Diagnostics.Debug.WriteLine("server thread started");
            Thread.CurrentThread.Name = "apocalypse";
            try
            {
                using (NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("ClosingPipe", PipeDirection.In, 1, PipeTransmissionMode.Byte))
                {
                    string line;

                    namedPipeServer.WaitForConnection();
                    StreamReader sr = new StreamReader(namedPipeServer);
                    Thread.Sleep(100);
                    line = sr.ReadLine();
                    handleRecvMsgFromPipe(line);
                    namedPipeServer.Disconnect();
                    namedPipeServer.Close();
                }
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("### " + e.Message + "\n" + e.StackTrace);
            }
        }

        private void handleRecvMsgFromPipe(string line)
        {
            this.outbox.Text = line;
        }

        private void buttonOpenFormClient_Click(object sender, EventArgs e)
        {
#if DEBUG

#else
            if (this.procClient == null)
            {
                try
                {
                    this.procClient = Process.Start(new ProcessStartInfo(CLIENTPROC));
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.Message, "Error");
                }
            }
#endif
        }
    }

那是客户端:

private ManualResetEvent threadResetEvent;
        private Thread threadHandlePipeSendLast;

        private string msgPipeSend;
        private volatile bool bMsgPipeSend;
        private bool done;

        public MainWindow()
        {
            InitializeComponent();
            this.threadResetEvent = new ManualResetEvent(false);
            this.Closing += (s, a) =>
            {
                System.Diagnostics.Debug.WriteLine("+++ FormClosing started.");
                this.threadHandlePipeSendLast = new Thread(new ThreadStart(this.HandleWindowClosing));
                this.threadHandlePipeSendLast.Start();
                while (!done)
                {
                    Thread.Sleep(1000);
                }
            };
        }

        private void HandleWindowClosing()
        {
            try
            {
                using (NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "ClosingPipe", PipeDirection.Out))
                {
                    namedPipeClient.Connect();
                    StreamWriter sw = new StreamWriter(namedPipeClient);
                    //sw.AutoFlush = true;
                    sw.WriteLine("last message");
                    namedPipeClient.WaitForPipeDrain();
                    namedPipeClient.Close();
                    this.done = true;
                }

            }
            catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.Message + "\n" + e.StackTrace); }
        }

谁能告诉我,为什么这在测试应用程序中有效而在实际应用程序中无效?我还在Thread.Join()程序的不同位置尝试了Thread.Sleep(x)到诸如WaitForPipeDrain之类的管道方法的各种方法(被忽略)。

0 个答案:

没有答案