使用With语句改写BeginInvoke委托代码触发空引用异常的原因咨询
为什么使用With语句改写后会抛出空引用异常?
这个问题我之前也碰到过,核心原因是VB.NET的With语句上下文不会被异步执行的匿名函数捕获,导致后续调用时找不到目标对象。
具体原因拆解:
- 当你用
With myGridView包裹代码时,这个With的上下文(也就是.指向的myGridView)只在当前同步执行的代码块内有效。 - 但你把匿名
Sub传给了BeginInvoke,这个Sub是异步执行的——它会被放到UI线程的消息队列里,等当前同步代码执行完后才会运行。 - VB.NET的闭包机制不会把
With的上下文对象(也就是myGridView)捕获到匿名函数里。当异步Sub真正执行时,原来的With上下文已经不存在了,这时候.就相当于在引用一个Nothing,自然就抛出空引用异常了。 - 反观你的原代码,直接通过
myGridView变量调用方法,这个变量会被闭包正常捕获,只要myGridView在异步执行时还未被销毁,就能正常访问。
修复方案:
你可以通过以下两种方式解决这个问题:
方案1:在With内部把目标对象存为局部变量
把myGridView赋值给一个局部变量,让闭包捕获这个变量,这样异步执行时就能正常访问:
With myGridView ' 把With的目标对象存为局部变量 Dim targetGrid = . BeginInvoke(New Action(Sub() Dim i As Integer = 0 Do While i < selectedRows.Count targetGrid.SelectRow(targetGrid.GetRowHandle(selectedRows(i))) i += 1 Loop End Sub)) End With
方案2:直接在匿名函数里引用原变量
放弃在异步函数里使用With的.,直接用myGridView调用方法,和你的原代码逻辑保持一致:
With myGridView BeginInvoke(New Action(Sub() Dim i As Integer = 0 Do While i < selectedRows.Count myGridView.SelectRow(myGridView.GetRowHandle(selectedRows(i))) i += 1 Loop End Sub)) End With
内容的提问来源于stack exchange,提问作者Nidx
相关产品推荐
相关产品推荐

