C#管道通讯及传输信息丢失的原因

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

相关推荐
咖啡の猫5 小时前
Python字典的查询操作
数据库·python·c#
czhc11400756637 小时前
c# 1213
开发语言·数据库·c#
xiaoid7 小时前
C#向jave平台的API接口推送
c#·post·webapi
小猪快跑爱摄影9 小时前
【AutoCad 2025】【C#】零基础教程(三)——获取选中的 Entity 插件 =》 初识 Entity 派生类
c#·autocad
czhc114007566310 小时前
c#w 1214
开发语言·c#
用户2986985301410 小时前
C# 中如何从 URL 下载 Word 文档:基于 Spire.Doc 的高效解决方案
后端·c#·.net
wangbing112511 小时前
将swagger在线文档转为word
microsoft·c#·word
mangge0811 小时前
定时刷新已经登录过的网页c#
c#
走错路的程序员12 小时前
C语言单片机与C#上位机之间传递大量参数比较好的实践方案
c语言·单片机·c#
辜月廿七13 小时前
C#字符串相关知识
c#