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

【26】C#实战篇—— 多个线程函数对同一个 Excel 文件进行写操作引起的文件冲突问题,解决方法

文章目录

  • 1 问题描述
  • 2 锁机制确保对Excel文件的写操作是线程安全的
  • 3 为什么是readonly?不是要写数据吗?

1 问题描述

现在cam1Func ~ cam5Func共5个相机测试的功能函数,C#开启5个线程同时运行这5个camFunc函数,

这5个camFunc都要调用 同一个名为 “Data_P0.xlsx"的Excel文件, 那么这就导致Data_P0.xlsx文件冲突

string m_ExcelName = "../Data/Data_P0.xlsx";public void Cam1Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[0]){m_Excel_Helper.SaveData(m_ExcelName, "cam1", "B6", BackVal, Variance, LWidth, spacingRows);isSaveData[0] = true;}// ...
}public void Cam2Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[1]){m_Excel_Helper.SaveData(m_ExcelName, "cam2", "B4", BackVal, Variance, LWidth, spacingRows);isSaveData[1] = true;}// ...
}public void Cam3Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[2]){m_Excel_Helper.SaveData(m_ExcelName, "cam3", "B2", BackVal, Variance, LWidth, spacingRows);isSaveData[2] = true;}// ...
}public void Cam4Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[3]){lock (excelLock){m_Excel_Helper.SaveData(m_ExcelName, "cam4", "F6", BackVal, Variance, LWidth, spacingRows);}isSaveData[3] = true;}// ...
}public void Cam5Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[4]){m_Excel_Helper.SaveData(m_ExcelName, "cam5", "F2", BackVal, Variance, LWidth, spacingRows);isSaveData[4] = true;}// ...
}

2 锁机制确保对Excel文件的写操作是线程安全的

为了解决同时对同一个 Excel 文件进行写操作引起的文件冲突问题,可以使用锁(lock)机制来确保每次只有一个线程能够访问文件。这样可以避免并发写入时的冲突。

可以使用 C# 中的 lock 关键字来实现这一点。下面是修改后的代码示例:

在类的开头定义这个静态锁对象,这个对象 是 Cam1Func 到 Cam5Func共用的;

// 定义一个静态对象用于锁
private static readonly object excelLock = new object();

然后在每个相机函数中使用这个锁对象来确保写操作是线程安全的。例如:

string m_ExcelName = "../Data/Data_P0.xlsx";public void Cam1Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[0]){// 使用锁机制确保对Excel文件的写操作是线程安全的,避免多线程并发写入时的冲突lock (excelLock){m_Excel_Helper.SaveData(m_ExcelName, "cam1", "B6", BackVal, Variance, LWidth, spacingRows);}isSaveData[0] = true;}// ...
}public void Cam2Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[1]){lock (excelLock){m_Excel_Helper.SaveData(m_ExcelName, "cam2", "B4", BackVal, Variance, LWidth, spacingRows);}isSaveData[1] = true;}// ...
}public void Cam3Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[2]){lock (excelLock){m_Excel_Helper.SaveData(m_ExcelName, "cam3", "B2", BackVal, Variance, LWidth, spacingRows);}isSaveData[2] = true;}// ...
}public void Cam4Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[3]){lock (excelLock){m_Excel_Helper.SaveData(m_ExcelName, "cam4", "F6", BackVal, Variance, LWidth, spacingRows);}isSaveData[3] = true;}// ...
}public void Cam5Func(bool isProcess, CancellationToken cancellationToken)
{// 类似的代码结构// ...if (LWidth[0] != 0 && !isSaveData[4]){lock (excelLock){m_Excel_Helper.SaveData(m_ExcelName, "cam5", "F2", BackVal, Variance, LWidth, spacingRows);}isSaveData[4] = true;}// ...
}

3 为什么是readonly?不是要写数据吗?

readonly 关键字用于确保 excelLock 对象在创建之后不能被更改。这是一个非常好的实践,因为锁对象不需要改变,只需要在多个线程之间共享它。将锁对象定义为 readonly 可以确保在整个应用程序运行期间它的引用不会被意外改变,从而避免潜在的线程安全问题。

与写/读数据无关,即使你要写数据,锁对象本身并不会存储数据或执行写操作。锁对象只是用于同步对资源的访问,确保每次只有一个线程能够访问该资源。在这种情况下,readonly 确保了锁对象在程序的生命周期内是唯一且不变的。

http://www.dtcms.com/a/322496.html

相关文章:

  • 代码随想录day60图论10
  • 使用 Ansys Discovery 进行动态设计和分析
  • Mac屏幕取色不准?探究原理和换算规则
  • Linux文件系统基石:透彻理解inode及其核心作用
  • LeetCode111~130题解
  • ABP VNext + Akka.NET:高并发处理与分布式计算
  • 【AGI】GPT-5:博士级AI助手的全面进化与协作智能时代的黎明
  • 如何输出一篇高质量的版本测试策略
  • WebGIS视角下基孔肯雅热流行风险地区分类实战解析
  • jupyter服务器创建账户加映射对外账户地址
  • stm32项目(24)——基于STM32的汽车CAN通信系统
  • React中实现完整的登录鉴权与权限控制系统
  • (一)React复习小满(userImmer/userMemo/useContext/userCallback/userRef)
  • 需求评审需要哪些角色参与
  • 嵌入式 - Linux软件编程
  • Web文件上传:本地与云存储实战
  • day 36_2025-08-09
  • 如何在 Ubuntu 24.04 LTS Linux 上安装 Azure Data Studio
  • C# 通过第三方库INIFileParser管理INI配置文件
  • Golang的本地缓存freecache
  • Linux中Docker redis介绍以及应用
  • Kubernetes(K8s)不同行业的典型应用场景及价值分析 原创
  • 【31】C#实战篇——获取路径下的文件名(不包含路径和扩展名),并分离出文件名`fileName` ,文件名编号`SN`,文件名前缀`WMT`
  • 功能测试中常见的面试题-二
  • kettle插件-kettle MinIO插件,轻松解决文件上传到MinIO服务器
  • Nginx高性能web服务器
  • 如何衡量需求的紧急程度
  • 单片机输出高电平的两种方式
  • Spring Boot自定义Starter:从原理到实战全解析
  • TDengine IDMP 产品基本概念