编辑
2025-09-22
C#
00

内存泄露是指在程序运行过程中,已分配的内存由于某些原因未能释放,导致随着程序的运行时间越长,占用的内存越多,最终可能导致程序运行缓慢甚至崩溃。在 C# .NET 环境中,尽管有垃圾回收(GC)机制帮助管理内存,但仍有一些情况会导致内存泄露。本文将通过示例探讨几种常见的内存泄露情况及其应用场景,并提供测试方法。

事件订阅未取消

应用场景

在 .NET 中,事件是实现对象间通信的一种机制。如果订阅者对象订阅了发布者对象的事件,但在不再需要时未取消订阅,那么发布者将持续持有订阅者的引用,导致订阅者对象无法被垃圾回收。

示例

C#
// 定义一个事件发布者类 public class EventPublisher { // 声明一个事件,使用 EventHandler<TEventArgs> 委托,这里的事件数据类型为 EventArgs public event EventHandler<EventArgs> MyEvent; // 触发事件的方法 public void RaiseEvent() { // ?.Invoke 安全地触发事件。如果 MyEvent 不为 null,则调用所有订阅者的方法 MyEvent?.Invoke(this, EventArgs.Empty); } } // 定义一个事件订阅者类 public class EventSubscriber { // 在构造函数中订阅事件 public EventSubscriber(EventPublisher publisher) { // 订阅 publisher 发布的 MyEvent 事件 publisher.MyEvent += Publisher_MyEvent; } // 事件处理方法,当事件被触发时执行 private void Publisher_MyEvent(object sender, EventArgs e) { // 输出消息表示事件已接收 Console.WriteLine("Event received."); } } // 测试代码 var publisher = new EventPublisher(); var subscriber = new EventSubscriber(publisher); publisher.RaiseEvent(); // 此时应取消订阅,否则 subscriber 无法被 GC 回收 // publisher.MyEvent -= subscriber.Publisher_MyEvent;

image.png

编辑
2025-09-22
C#
00

在 .NET 应用程序中,提高执行效率和响应速度是开发者追求的目标之一。随着多核处理器的普及,利用并行编程来充分利用多核处理器的能力成为了提高应用程序性能的有效手段。System.Threading.Tasks.Parallel 类提供了一种简单而强大的并行编程模型,使得开发者能够更加方便地实现并行操作。

本文将介绍 Parallel 类的基本用法,并通过几个实例展示如何在 .NET 应用中使用 Parallel 来提升性能。

应用场景

Parallel 类适用于以下几种场景:

  • 数据并行处理:当需要对数据集合中的每个元素执行相同的操作时,可以使用数据并行来加速处理过程。
  • 并行任务执行:当有多个相互独立的任务需要执行时,可以并行地执行这些任务以减少总体执行时间。

示例 1:并行循环

假设我们需要对一个整数数组的每个元素执行计算密集型操作。

串行实现

C#
int[] numbers = Enumerable.Range(1, 1000000).ToArray(); // 串行处理 var watch = Stopwatch.StartNew(); foreach (var num in numbers) { // 执行某些计算密集型操作 Compute(num); } watch.Stop(); Console.WriteLine($"串行执行时间: {watch.ElapsedMilliseconds} ms");
编辑
2025-09-22
C#
00
编辑
2025-09-22
C#
00

Modbus协议作为工业自动化领域中最为广泛应用的通信协议之一,由于其简洁、开放和高效的特点,一直以来被用于PLC、传感器、远程监控系统等设备之间的数据交换。其中,功能码在整个Modbus通信过程中起到了至关重要的作用,其不仅决定了设备所需执行的具体动作,同时也直接反映了报文结构及数据传输的细节。


Modbus协议概述

Modbus协议由Modbus协会制定,其核心思想是建立主从(主机-从机)的通信模型,以实现多个设备之间可靠、高效的数据交换。在该协议中,消息帧(或报文)由从站地址、功能码、数据域以及错误校验部分(通常为CRC校验)构成。功能码是一字节数据,其取值范围为0~127(0x00~0x7F),而出现异常时,功能码会在基础功能码上加上0x80(如功能码0x01异常响应为0x81),从而反映出错误信息。

Modbus通信支持多种物理层(如RS-232、RS-485、TCP/IP等)以及多种数据类型,主要包括位操作(针对单个bit)、寄存器操作(针对16位字)和部分特殊诊断操作。各类功能码对应不同操作内容,如读取或写入线圈状态、读取或写入保持寄存器、诊断功能以及自定义操作指令等,这些都在后续章节中逐一详述。

此外,Modbus设备中数据通常存储在四大数据块中:线圈(Coils)、离散输入(Discrete Inputs)、保持寄存器(Holding Registers)及输入寄存器(Input Registers),这为不同应用场景提供了丰富的数据类型。本文研究重点聚焦在功能码的工作原理和报文结构方面,而不额外展开设备应用场景或与其他协议的比较。


位操作功能码详解

Modbus中涉及位操作的数据主要指单个位(bit)数据,即用于表示布尔量(ON/OFF)的状态。位操作相关的功能码通常包括读取线圈状态、读取离散输入状态以及写操作中的单个或多个线圈控制。下面我们从读取操作和写入操作两大类依次解析。

image.png

编辑
2025-09-22
C#
00

Modbus 是工业自动化和控制系统中最常用的通信协议之一,其自 1979 年由 Modicon(现为施耐德电气的一部分)推出以来,已广泛应用于 PLC、传感器、仪表等设备间的数据传输。本文将全面探讨 Modbus 数据模型及数据转换技术的理论与实践,主要内容涉及数据模型定义、地址偏移、端序处理、浮点数及多寄存器数据转换等关键技术问题。通过对理论基础的剖析和实际案例的详细说明,本文旨在为工程师和开发人员提供一份权威、实用的参考文档,帮助他们准确解读和实现 Modbus 数据通信的各项需求。


Modbus 数据模型解析

image.png

Modbus 协议将数据抽象为几种不同的数据模型,主要包括:

  1. 线圈(Coils)
    • 访问权限:可读写
    • 描述:代表单个位,用于控制开关状态。
  2. 离散输入(Discrete Inputs)
    • 访问权限:只读
    • 描述:代表单个位,用于读取输入状态。
  3. 输入寄存器(Input Registers)
    • 访问权限:只读
    • 描述:以 16 位整数(范围 0-65535)形式存储数据,常用于传感器读数等。
  4. 保持寄存器(Holding Registers)
    • 访问权限:可读写
    • 描述:以 16 位整数形式存储数据,常用于配置参数或保存模拟量值。