以下是C#管道通訊客戶端/服務端共用類
namespace PipeCommunication
{
? ? /// <summary>
? ? /// 管道信息回調通知
? ? /// </summary>
? ? /// <param name="msg"></param>
? ? public delegate void PipeMessageEventHandler(string msg);
? ? public class PipeCommunicateCenter
? ? {
? ? ? ? public event PipeMessageEventHandler OnPipeMessageReceiveEvent;
? ? ? ? private string _pipeServerName = "";
? ? ? ? private string _pipeClientName = "";
? ? ? ? public PipeCommunicateCenter(string pipeServerName, string pipeClientName)
? ? ? ? {
? ? ? ? ? ? _pipeServerName = pipeServerName;
? ? ? ? ? ? _pipeClientName = pipeClientName;
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 發送消息
? ? ? ? /// </summary>
? ? ? ? /// <param name="msg"></param>
? ? ? ? public void ClientSend(string msg)
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", _pipeClientName, PipeDirection.InOut))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? pipeClient.Connect(3000);
? ? ? ? ? ? ? ? ? ? using (StreamWriter sw = new StreamWriter(pipeClient))
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? sw.AutoFlush = true;
? ? ? ? ? ? ? ? ? ? ? ? sw.WriteLine(msg);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? {
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? Thread thPipLsiten;
? ? ? ? /// <summary>
? ? ? ? /// 啟動監聽
? ? ? ? /// </summary>
? ? ? ? public void StartPipListen()
? ? ? ? {
? ? ? ? ? ? thPipLsiten = new Thread(PipListen);
? ? ? ? ? ? thPipLsiten.IsBackground = true;
? ? ? ? ? ? thPipLsiten.Start();
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 監聽線程是否存在
? ? ? ? /// </summary>
? ? ? ? /// <returns></returns>
? ? ? ? public bool GetPipListenIsAlive()
? ? ? ? {
? ? ? ? ? ? return thPipLsiten == null ? false : thPipLsiten.IsAlive;
? ? ? ? }
? ? ? ? bool hasRead = false;
? ? ? ? /// <summary>
? ? ? ? /// 監聽線程
? ? ? ? /// </summary>
? ? ? ? private void PipListen()
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? while (!isExist)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? using (NamedPipeServerStream pipeServer = new NamedPipeServerStream(_pipeServerName, PipeDirection.InOut))
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? pipeServer.WaitForConnection();//等待連接,程序會阻塞在此處,直到有一個連接到達
? ? ? ? ? ? ? ? ? ? ? ? hasRead = false;
? ? ? ? ? ? ? ? ? ? ? ? try
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? while (!hasRead)
? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? using (StreamReader sr = new StreamReader(pipeServer))
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? var read = sr.ReadLine();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (!string.IsNullOrEmpty(read))
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? hasRead = true;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //MessageBox.Show("pipread:" + read);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NotifyPipeMessageReceive(read);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.Sleep(10);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? catch (Exception ex2)
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? Thread.Sleep(10);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception ex1)
? ? ? ? ? ? {
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 通知收到信息
? ? ? ? /// </summary>
? ? ? ? /// <param name="msg"></param>
? ? ? ? private void NotifyPipeMessageReceive(string msg)
? ? ? ? {
? ? ? ? ? ? OnPipeMessageReceiveEvent?.Invoke(msg);
? ? ? ? }
? ? ? ? bool isExist = false;
? ? ? ? /// <summary>
? ? ? ? /// 退出監聽管道
? ? ? ? /// </summary>
? ? ? ? public void ExistPipeCommunicate()
? ? ? ? {
? ? ? ? ? ? isExist = true;
? ? ? ? }
? ? }
}
使用條件:
客戶端/服務端通訊均在線程中使用
問題:
在使用過程中偶爾發生通訊丟失,程式假死,程式邏輯無法正常走下去.
原因分析:
因為程式中異步線程
使用了Application.DoEvents()方法.
在C# WinForms中,Application.DoEvents()
?方法的作用是強制處理當前消息隊列中的所有Windows消息,例如用戶輸入(點擊、鍵盤事件)、界面重繪等。它的主要意義是讓應用程序在長時間運行的代碼中保持界面響應,但需謹慎使用。
當執行耗時操作(如循環、復雜計算或阻塞任務)時,UI線程會被占用,導致界面“卡死”(無法響應用戶操作或更新顯示)。調用?Application.DoEvents()
?會臨時處理消息隊列中的事件,讓界面保持“假響應”。
解決方案:
在非UI線程中禁止使用?Application.DoEvents()
異步線程強制使用
?Application.DoEvents()可能會導致
事件處理順序混亂,界面更新異常,邏輯依賴破壞等問題.