System.InvalidOperationException:对象当前正在其他地方使用

server/2025/3/26 4:08:37/

Form窗口当UI更新被多个地方的调用,并且存在冲突时,可能出现以上错误。

比如UI正在初始化,结果另外一个线程调用了更改界面的函数,则会出现上面的错误,因为这个错误是偶发的,所以暂无办法稳定复现。

解决办法,利用加锁的方式,避免UI竞争。

在C#窗体应用中,通过以下步骤实现‌全局锁机制‌,可有效避免因多线程或异步操作导致的对象正在其他地方使用异常:
‌一、全局锁实现方案‌
‌1. 定义全局锁对象‌

在Form类中声明一个私有锁对象,用于同步所有共享资源的访问:

public partial class MainForm : Form
{// 全局锁对象(推荐使用引用类型)private readonly object _globalLock = new object();// 若涉及异步操作,使用SemaphoreSlimprivate readonly SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);
}

‌2. 同步访问共享资源‌

在操作‌非UI共享资源‌(如文件、集合、数据库连接)时,使用lock或Monitor强制串行化:

private void UpdateData()
{lock (_globalLock)  // 进入临界区{// 操作共享资源(如List<T>、文件流等)sharedList.Add(newItem);}  // 自动释放锁
}

‌3. 异步操作中的锁管理‌

若涉及async/await,使用SemaphoreSlim代替lock:

private async Task UpdateDataAsync()
{await _asyncLock.WaitAsync();  // 异步等待锁try{// 异步操作共享资源await WriteToFileAsync("data.txt");}finally{_asyncLock.Release();  // 确保释放锁}
}

‌4. UI控件的线程安全访问‌

对UI控件的操作,需通过Invoke/BeginInvoke切换到主线程,并‌结合全局锁‌:

private void SafeUpdateUI(string text)
{if (label1.InvokeRequired){BeginInvoke(new Action(() => SafeUpdateUI(text)));return;}lock (_globalLock)  // 保护UI操作相关资源{label1.Text = text;progressBar1.Value = CalculateProgress();}
}

‌二、关键场景与优化‌
‌1. 避免死锁‌

    ‌锁嵌套规则‌:确保所有代码路径以‌相同顺序‌获取锁。
    错误示例:

    void MethodA(){lock (lockA){lock (lockB) { ... }  // 若其他方法先锁B再锁A,可能导致死锁}}

    ‌超时机制‌:使用Monitor.TryEnter防止无限等待:

    if (Monitor.TryEnter(_globalLock, TimeSpan.FromSeconds(5))){try { ... }finally { Monitor.Exit(_globalLock); }}else{throw new TimeoutException("获取锁超时");}

‌2. 性能优化‌

    ‌缩小临界区‌:仅在操作共享资源时持有锁,减少锁的持有时间:

    var tempData = FetchData();  // 非临界区操作lock (_globalLock){sharedList.AddRange(tempData);  // 快速操作}

    ‌读写分离‌:对读多写少的场景,使用ReaderWriterLockSlim:
 

    private ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();// 读操作public string ReadData(){_rwLock.EnterReadLock();try { return sharedData.ToString(); }finally { _rwLock.ExitReadLock(); }}// 写操作public void WriteData(string value){_rwLock.EnterWriteLock();try { sharedData.Append(value); }finally { _rwLock.ExitWriteLock(); }}

‌三、完整示例‌
‌场景‌:窗体启动时异步加载数据,同时允许用户手动刷新,确保两个操作不会冲突。
 

public partial class MainForm : Form
{private List<string> _dataCache = new List<string>();private readonly SemaphoreSlim _dataLock = new SemaphoreSlim(1, 1);public MainForm(){InitializeComponent();this.Load += MainForm_Load;btnRefresh.Click += BtnRefresh_Click;}private async void MainForm_Load(object sender, EventArgs e){await LoadDataAsync();}private async void BtnRefresh_Click(object sender, EventArgs e){await LoadDataAsync();}private async Task LoadDataAsync(){await _dataLock.WaitAsync();try{// 模拟耗时数据加载var newData = await Task.Run(() => FetchDataFromDatabase());// 切换到UI线程更新控件BeginInvoke(new Action(() =>{lock (_dataLock)  // 确保与其他UI操作互斥{_dataCache = newData;dgvData.DataSource = _dataCache;}}));}finally{_dataLock.Release();}}
}

‌四、注意事项‌

    ‌锁的作用域‌
    确保锁仅用于保护‌真正共享的资源‌,避免滥用导致性能下降。

    ‌UI线程与锁的关系‌
    Invoke/BeginInvoke本身不提供线程安全,需结合锁保护非原子操作(如先读后写)。

    ‌资源释放‌
    在窗体关闭时释放锁相关资源:

    protected override void OnFormClosing(FormClosingEventArgs e){_asyncLock?.Dispose();base.OnFormClosing(e);}

通过上述方法,可实现窗体级别的全局线程安全,彻底解决对象正在其他地方使用异常。


http://www.ppmy.cn/server/179138.html

相关文章

31天Python入门——第9天:再学函数

你好&#xff0c;我是安然无虞。 文章目录 再学函数1. 变量在函数中的作用域2. 函数的参数传递.补充学习: 不定长参数*args和**kwargs 3. 值传递和引用传递补充学习: 把函数作为参数传递 4. 匿名函数5. python中内置的常用函数zip()map()filter()all()any() 6. 函数练习 再学函…

Java 24 学习

一、Java 24的核心新功能 1、语言特性增强 模式匹配与原始类型支持&#xff08;JEP 488&#xff09;&#xff1a;允许在instanceof和switch中使用原始类型&#xff0c;简化模式匹配代码&#xff0c;尤其适用于AI推理场景912。 灵活的构造函数体&#xff08;JEP 492&#xff…

Python实战(3)-数据库操作

前面说过&#xff0c;可用的SQL数据库引擎有很多&#xff0c;它们都有相应的Python模块。这些数据库引擎大都作为服务器程序运行&#xff0c;连安装都需要有管理员权限。为降低Python DB API的使用门槛&#xff0c;我选择了一个名为SQLite的小型数据库引擎。它不需要作为独立的…

大模型tokenizer重构流程

大模型tokenizer层再训练&#xff08;选取Qwen7B试验&#xff0c;重构token层&#xff09; 最近公司可能想训练一个蛋白质大模型&#xff0c;需要了解一下大模型tokenizer重构&#xff0c;之后可能要训练&#xff0c;这里做了一定的总结。 文章目录 1. 首先查看Qwen2.5 7B基本…

【Java/数据结构】栈(Stack)

本博客将带大家一起学习基本数据结构之一——栈&#xff08;Stack&#xff09;&#xff0c;虽然Java当中的Stack集合已经被Deque&#xff08;双端队列&#xff09;替代了&#xff0c;但是他的基本思想和实现还是有必要学习的。 一.初识栈 1.基本概念 堆栈又名栈&#xff08;st…

Shopify Checkout UI Extensions

结账界面的UI扩展允许应用开发者构建自定义功能&#xff0c;商家可以在结账流程的定义点安装&#xff0c;包括产品信息、运输、支付、订单摘要和Shop Pay。 Shopify官方在去年2024年使用结账扩展取代了checkout.liquid&#xff0c;并将于2025年8月28日彻底停用checkout.liquid…

三层网络 (服务器1 和 服务器2 在不同网段)

服务器1 和 服务器2 在不同网段&#xff0c;并且通过三层交换机实现通信 1. 网络拓扑 假设网络拓扑如下&#xff1a; 服务器1&#xff1a; mac0&#xff1a;IP 地址 192.168.1.10/24&#xff0c;网关 192.168.1.1 mac1&#xff1a;IP 地址 10.0.1.10/24&#xff0c;网关 10.0…

SQL 版本历史

SQL&#xff08;Structured Query Language&#xff09;是一种用于管理和操作关系数据库的标准语言。SQL标准由多个组织制定和维护&#xff0c;主要包括以下几个版本&#xff1a; SQL-86 (SQL-87): 这是SQL的第一个官方标准&#xff0c;由ANSI&#xff08;美国国家标准协会&…