编辑
2025-10-11
C#
00

在C#的多线程编程中,Mutex 是一种用于同步多个线程的机制。它不仅适用于进程间的线程同步,还可以在同一进程内用于保护共享资源。本文将详细介绍 Mutex 的特点、用法,并提供多个示例以示范其应用。

Mutex 的特点

  • 跨进程同步Mutex 允许在不同进程之间进行同步,这使得它在处理需要进程间通信的场景时相当有用。
  • 独占性访问:只有一个线程可以获得 Mutex,其他线程必须等待,直到该线程释放 Mutex
  • 超时控制Mutex 允许设置超时。如果线程在指定时间内无法获得锁,可以选择放弃。
  • 简单易用Mutex 提供了清晰的接口,易于程序员使用。

使用 Mutex 的基本语法

以下是 Mutex 的基本用法示例:

C#
Mutex mutex = new Mutex(); mutex.WaitOne(); //请求锁 // ... 访问共享资源 mutex.ReleaseMutex(); //释放锁

示例:使用 Mutex 实现线程安全的计数器

以下示例展示了如何使用 Mutex 来实现一个线程安全的计数器,确保只有一个线程可以对计数器进行更新。

C#
using System; using System.Threading; class Program { private static int counter = 0; // 共享资源 private static Mutex mutex = new Mutex(); // 创建 Mutex 实例 static void Main(string[] args) { Thread[] threads = new Thread[5]; for (int i = 0; i < threads.Length; i++) { threads[i] = new Thread(IncrementCounter); threads[i].Start(); } foreach (var thread in threads) { thread.Join(); } Console.WriteLine($"最终计数器的值: {counter}"); } static void IncrementCounter() { for (int i = 0; i < 1000; i++) { mutex.WaitOne(); // 请求锁 try { counter++; // 增加计数 } finally { mutex.ReleaseMutex(); // 确保释放锁 } } } }

image.png

编辑
2025-10-11
C#
00

随着 .NET 6 的发布,LINQ 中新增了两个便捷的扩展方法:

  • MinBy(Func<T, TKey> keySelector)
  • MaxBy(Func<T, TKey> keySelector)

它们能根据指定的键(keySelector)从集合中一次性取得最小值或最大值所在的整个对象(而不仅仅是数值)。拥有这两个方法后,我们无需再手工使用 OrderBy() + First() 或者 OrderByDescending() + First() 的组合来取极值对象,代码变得更加简洁,也能避免没必要的排序操作,效率更高。

准备工作

在开始动手实验之前,我们先定义一个简单的 Student 记录类型,并创建一个学生列表,包含学生的姓名和分数等信息。示例如下:

C#
namespace AppMin { public record Student(string Name, int Marks); internal class Program { static void Main(string[] args) { // 创建学生列表 var students = new List<Student> { new Student("张三", 520), new Student("李四", 480), new Student("王五", 550), new Student("张飞", 430), new Student("关羽", 550) }; // 打印数据,确保数据已经正确初始化 foreach (var student in students) { Console.WriteLine($"{student.Name} - {student.Marks}"); } } } }
编辑
2025-10-11
C#
00

在嵌入式系统、物联网(IoT)和工业通讯领域,串口通讯仍然是一种广泛使用的通信方式。本文将深入探讨如何使用C#实现一个健壮、高效的异步串口通讯管理器。

关键设计理念

异步编程

异步编程是现代.NET应用程序的重要特性,它允许:

  • 非阻塞的I/O操作
  • 提高应用程序的响应性
  • 有效利用系统资源

主要特性

我们的串口管理器将具备以下特性:

  • 异步连接和读取
  • 错误处理
  • 灵活的数据接收机制
  • 资源释放管理

代码解析

类定义与构造函数

C#
public class SerialPortManager : IDisposable { private SerialPort _serialPort; private readonly string _portName; private readonly int _baudRate; private CancellationTokenSource _cancellationTokenSource; // 数据接收事件 public event EventHandler<byte[]> DataReceived; public SerialPortManager(string portName, int baudRate) { _portName = portName; _baudRate = baudRate; _cancellationTokenSource = new CancellationTokenSource(); } }
编辑
2025-10-11
C#
00

在 C# 的 LINQ 查询中,SelectSelectMany 经常使用来处理集合或可查询对象。两者有些相似之处,但也有明显区别:

Select:将集合中的每个元素映射(投影)到一个新的形式,最终返回与原集合长度相同的序列。

SelectMany:针对集合中的每个元素返回一个可枚举序列,然后将所有子序列“压平”(Flatten)为一个新的序列。

Select 示例

以下例子演示如何使用 Select 将字符串列表中的每个元素转换成大写形式:

C#
public class Program { public static void Main() { var fruits = new List<string> { "apple", "banana", "cherry" }; // 使用 Select 把每个字符串都转换为大写 var upperFruits = fruits.Select(fruit => fruit.ToUpper()); foreach (var item in upperFruits) { Console.WriteLine(item); } } }

image.png

编辑
2025-10-10
C#
00

在C#的多线程编程中,lock 是一种非常常用的同步机制,用于保护共享资源,防止多个线程同时访问造成的数据不一致。本文将详细介绍 lock 的特点、用法,以及相关的示例。

lock 的特点

  • 独占访问:在 lock 关键字块内,只允许一个线程进入,其他线程会被阻塞,直到当前线程释放锁。
  • 防止死锁lock 通过申请对象的互斥锁(monitor)来防止其他线程进入同一代码块,可以有效避免由于多个线程同时访问共享资源而导致的死锁情况。
  • 易于使用lock 关键字语法简单,使得多线程同步的编码过程更加清晰,降低了错误的可能性。
  • 优化性能:与其他同步方式(如 MutexSemaphore)相比,lock (其实是 Monitor 的一种语法糖)在执行上更为轻量,适合于保护简单的共享数据。

使用 lock 的基本语法

lock 的基本语法如下:

C#
lock (object lockObject) { // 需要保护的代码块 }

lockObject 是一个用于同步的对象,通常是一个私有的对象,以防其他代码也使用它。

示例:使用 lock 进行线程安全的计数器