.Net中如何在线程调用中传递ByRef参数或获取对应读写委托
问题根因
.NET 内置的Action(Of T)、Func(Of TResult)等泛型委托的参数默认都是按值传递,不支持ByRef修饰的参数,所以你定义的Sub(ByRef t As MyType)无法匹配Action(Of MyType)的签名。同时Thread.Start方法的参数是Object类型,传递值类型时只会生成副本,无法直接实现按引用修改的效果。
解决方案
方案1:用引用类型包装值类型(推荐)
值类型继承自Structure,默认按值传递,我们可以用一个引用类型的包装类承载值,传递包装类的引用就等价于实现了按引用操作原始值的效果,全程可以用标准的内置委托,兼容性最好。
首先定义通用包装类:
Public Class ValueWrapper(Of T As Structure) Public Property Value As T End Class
改造后的业务代码:
Public Sub UseLater(Of T As Structure)(wrapper As ValueWrapper(Of T), m As Mutex, callback As Action(Of T)) m.WaitOne() Try callback(wrapper.Value) Finally m.ReleaseMutex() End Try End Sub '' 调用侧代码 Dim getterLock As New Mutex() Dim buffer As MyType = Nothing ' 包装要传递的原始值 Dim objWrapper As New ValueWrapper(Of MyType) With {.Value = MyObject} Dim threadhelper As Action = Sub() UseLater(Of MyType)(objWrapper, getterLock, Sub(t) buffer = t) End Sub getterLock.WaitOne() Dim getLater As New Thread(threadhelper) getLater.Start() Dim getter As Func(Of MyType) = Function() getterLock.ReleaseMutex() Return buffer End Function
方案2:自定义支持ByRef的委托
如果你确实需要保留ByRef参数的写法,可以自定义匹配签名的委托类型,配合闭包捕获要传递的变量即可:
首先自定义委托:
' 声明支持ByRef参数的自定义委托 Public Delegate Sub ByRefAction(Of T As Structure)(ByRef t As T)
改造后的业务代码:
Public Sub UseLater(Of T As Structure)(ByRef t As T, m As Mutex, callback As ByRefAction(Of T)) m.WaitOne() Try callback(t) Finally m.ReleaseMutex() End Try End Sub '' 调用侧代码 Dim getterLock As New Mutex() Dim buffer As MyType = Nothing Dim target As MyType = MyObject ' 要传递的原始变量 ' 闭包直接捕获target变量,无需通过Thread.Start传参 Dim threadhelper As ThreadStart = Sub() UseLater(Of MyType)(target, getterLock, Sub(ByRef t_) buffer = t_) End Sub getterLock.WaitOne() Dim getLater As New Thread(threadhelper) getLater.Start() Dim getter As Func(Of MyType) = Function() getterLock.ReleaseMutex() Return buffer End Function
方案选型建议
- 跨方法、跨作用域传递参数时优先选方案1,符合.NET常规编码规范,逻辑更易维护
- 小范围临时使用时可以选方案2,代码更轻量化
内容的提问来源于stack exchange,提问作者user13507303
相关产品推荐
相关产品推荐

