以下是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()可能会导致
事件处理顺序混乱,界面更新异常,逻辑依赖破坏等问题.