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

相关推荐
bugcome_com1 小时前
阿里云 OSS C# SDK 使用实践与参数详解
阿里云·c#
懒人咖11 小时前
缺料分析时携带用料清单的二开字段
c#·金蝶云星空
bugcome_com12 小时前
深入了解 C# 编程环境及其开发工具
c#
wfserial13 小时前
c#使用微软自带speech选择男声仍然是女声的一种原因
microsoft·c#·speech
阔皮大师15 小时前
INote轻量文本编辑器
java·javascript·python·c#
kylezhao201916 小时前
C# 中的 SOLID 五大设计原则
开发语言·c#
啦啦啦_999916 小时前
Redis-5-doFormatAsync()方法
数据库·redis·c#
Porco.w17 小时前
C#与三菱PLC FX5U通信
网络·c#
E_ICEBLUE19 小时前
PPT 批量转图片:在 Web 预览中实现翻页效果(C#/VB.NET)
c#·powerpoint·svg
JQLvopkk21 小时前
C# 轻量级工业温湿度监控系统(含数据库与源码)
开发语言·数据库·c#