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

相关文章:

  • 信息革命对经济、货币体系及权力结构的颠覆性影响
  • 深入了解linux系统—— 进程控制
  • 虚拟现实(VR)与增强现实(AR)在教育领域的应用:开启沉浸式学习新时代
  • 006 yum和Linux生态
  • 可执行文件格式(ELF格式)以及进程地址空间第二讲【Linux操作系统】
  • 精益数据分析(46/126):深入剖析用户生成内容(UGC)商业模式
  • 各地级市儒家学校、学堂、孔庙数据
  • sizeof 和 strlen 的区别
  • 链表——C语言
  • Nacos源码—5.Nacos配置中心实现分析一
  • 多功能气体检测报警系统,精准监测,守护安全
  • 数据结构——排序(万字解说)初阶数据结构完
  • Java学习手册:ORM 框架性能优化
  • Unity WebGL、js发布交互
  • Oracle OCP认证考试考点详解083系列11
  • 什么是先验?(CVPR25)Detail-Preserving Latent Diffusion for Stable Shadow Removal论文阅读
  • 面试题 03.06 动物收容所
  • Node.js入门指南:开启JavaScript全栈开发之旅
  • C++从入门到实战(十三)C++函数模板与类模板初阶讲解
  • CentOS 7 基础环境安装脚本
  • 咸宁市委常委、市纪委书记官书云调任湖北省司法厅副厅长
  • 面对非专业人士,科学家该如何提供建议
  • 云南一餐馆收购长江野生鱼加工为菜品,被查处罚款
  • 19岁女生注射头孢离世后续:院方道歉,医生停职,监管介入
  • 数说母亲节|妈妈的妈妈带娃比例提升,托举效果如何?
  • 欧洲承诺投资6亿欧元吸引外国科学家