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

相关推荐
游乐码1 分钟前
C#List
开发语言·c#·list
Paine Zeng2 小时前
C# + SolidWorks 二次开发 -监听退出草图事件并自动执行逻辑
c#·solidworks二次开发·solidworks api
游乐码3 小时前
C#Dicitionary
算法·c#
SunnyDays10113 小时前
C# 实战:如何高效地将 HTML 转换为可编辑 Word 文档
c#·html转word
用户3721574261353 小时前
C# 实战:如何高效地将 HTML 转换为可编辑 Word 文档
c#
鱼干~4 小时前
【全栈知识点】全栈开发知识点
前端·人工智能·c#
yu85939584 小时前
WinForm 嵌入 WordExcel 实现方案
开发语言·microsoft·c#
躺平的赶海人4 小时前
C# 客户端性能优化(一):CPU 利用率获取与监控
c#
rockey62712 小时前
AScript如何实现中文脚本引擎
c#·.net·script·eval·expression·function·动态脚本
我是唐青枫14 小时前
C#.NET gRPC 深入解析:Proto 定义、流式调用与服务间通信取舍
开发语言·c#·.net