从ListBox对象中进行线程安全的读取操作是否可行?
关于ListBox跨线程读取的线程安全性及代码修正
读取操作的线程安全性
- WinForm控件的所有成员访问默认都要求在创建控件的UI线程执行,哪怕是只读操作也不属于线程安全的范畴。
- 就算你当前确认没有写入操作,直接跨线程读Items集合也存在风险:如果UI线程同时在修改Items(比如新增/删除/替换项),会出现读脏数据、索引越界、运行时异常等不可预期的问题。
- 所有跨线程的控件访问都必须通过
Invoke/BeginInvoke封送到UI线程执行,这是WinForm线程安全的标准方案。
现有代码的问题及修正方案
你写的代码问题出在InvokeRequired为True的分支:Invoke执行委托是有返回值的,你没有接收并返回这个值,导致这条执行路径没有返回值,不符合函数声明要求。
修正后的代码如下:
Private Delegate Function GetDetailsDelegate(ByVal index As Integer) As MySQLDetails Private Function GetDetails(index As Integer) As MySQLDetails If InvokeRequired Then ' 接收Invoke执行委托返回的结果,转换类型后返回 Return CType(Invoke(New GetDetailsDelegate(AddressOf GetDetails), {index}), MySQLDetails) Else Return CType(LstMySQL.Items.Item(index), MySQLDetails) End If End Function
修正说明:
- 补全了委托的返回值类型,避免后期类型转换出错
Invoke执行完委托后会返回委托的执行结果,转换为MySQLDetails类型后返回即可覆盖所有执行路径- 所有读取操作实际都在UI线程执行,完全符合WinForm线程安全要求,不会出现线程冲突问题
内容的提问来源于stack exchange,提问作者Richard Marell
相关产品推荐
相关产品推荐

