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

相关推荐
燃尽了,可无4 小时前
C#基础编程核心知识点总结
开发语言·c#
我不是程序猿儿6 小时前
【C#】观察者模式 + UI 线程调度、委托讲解
观察者模式·ui·c#
专注VB编程开发20年6 小时前
c# .net支持 NativeAOT 或 Trimming 的库是什么原理
前端·javascript·c#·.net
钢铁男儿7 小时前
C# 简单工厂模式(简单工厂模式如何工作)
前端·c#·简单工厂模式
isyoungboy9 小时前
c#实现鼠标mousemove事件抽稀,避免大数据阻塞网络
c#·计算机外设·远程桌面·deskflow
一枚小小程序员哈13 小时前
基于asp.net 的在线餐饮订餐系统的设计与实现/基于c#的网上订餐系统/餐厅管理系统
后端·c#·asp.net
好望角雾眠13 小时前
第三阶段数据库-7:sql中函数,运算符,常用关键字
数据库·笔记·sql·学习·sqlserver·c#
海绵宝宝汉堡包17 小时前
c# 项目 文件夹
开发语言·c#
曹牧20 小时前
C#:窗体间传值
c#
一个会的不多的人1 天前
C# NX二次开发:面收集器控件和曲线收集器控件详解
开发语言·c#