当前位置: 首页 > news >正文

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

http://www.xdnf.cn/news/325315.html

相关文章:

  • android中背压问题面试题及高质量回答范例
  • 前端面试测试题目(一)
  • 《Python星球日记》 第49天:特征工程与全流程建模
  • 认识tomcat(了解)
  • Android Studio开发安卓app 设置开机自启
  • RISC-V JTAG:开启MCU 芯片调试之旅
  • 鸿蒙知识总结
  • Promise 高频面试题
  • 证件阅读机在景区实名制应用场景的方案
  • 【数据库原理及安全实验】实验六 角色访问控制
  • 探索 C++ 语言标准演进:从 C++23 到 C++26 的飞跃
  • 轨迹预测笔记
  • 爽提“双核引擎”:驱动校园餐饮焕新升级
  • 直播数据大屏是什么?企业应如何构建直播数据大屏?
  • cursor配置mcp并使用
  • 2025-05-07-关于API Key 的安全管理办法
  • vue3+vite项目引入tailwindcss
  • ntdll!LdrpNameToOrdinal函数分析之二分查找
  • 数据可视化:php+echarts实现数据可视化
  • MySQL 中常见的日志
  • 《深度学习入门 基于Python的理论实现》思维导图
  • eclipse开发环境中缺少JavaEE组件如何安装
  • Go语言基础学习详细笔记
  • 数据实验分析
  • Transformer自学笔记
  • HarmonyOS 鸿蒙操作物联网设备蓝牙模块、扫描蓝牙、连接蓝牙和蓝牙通信
  • 如何查看电脑显卡配置参数 一文读懂
  • Python----神经网络(《Going deeper with convolutions》论文解读和GoogLeNet网络)
  • 第十二节:图像处理基础-图像平滑处理 (均值滤波、高斯滤波、中值滤波)
  • CTK的插件框架和QTUI集成方法