Luc*_*VdV 4 vb.net asynccallback synclock
我正在开发一个类库,它将为CLR应用程序提供异步通信.
SslStream上有异步读取(BeginRead),其中一个回调例程由多个流共享.我不希望在调试期间并行处理回调,所以我创建了一个关键部分:
Private Sub Callback_Read(ByVal ar As IAsyncResult)
Static OneAtATime As New Object
SyncLock OneAtATime
Dim ThisSslStream As SslStream = DirectCast(ar.AsyncState, SslStream)
...
End SyncLock
End Sub
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,这不起作用,至少在我在SyncLock块中设置断点时是这样.多个流的回调同时在其中运行,而无需在入口点等待,直到前一个线程离开它为止.
单步执行它是一场噩梦,特别是当流同时关闭(关闭)时:执行流1的行,执行流2的行,执行下一行1,执行下一行2,依此类推,通过整个块.
我想也许你需要的东西不仅仅是一个通用的"新对象",但后来我看到这里至少有一个关于堆栈溢出的答案,说明SyncLock正是我使用它的方式,只是"静态X作为新对象"在必须锁定的函数内创建同步对象.
是因为回调实际上来自.Net框架之外的win32线程,SyncLock在这里不起作用?
Static OneAtATime As New Object
Run Code Online (Sandbox Code Playgroud)
Static关键字是VB.NET实现者的一个相当重要的磨刀石.他们必须支持它,因为它在以前的Visual Basic版本中经常使用,省略它会给想要更新其工具的程序员带来太多困难.
但它的遗留行为与线程非常不兼容,线程在.NET中得到了非常强烈的支持.之前不是问题,因为旧的VB版本不支持创建线程.为该语句生成的MSIL代码量很大.您应该看看ildasm.exe实用程序.
它很大,因为它需要做什么.这是第一次输入方法时仅初始化变量一次.不是非常困难,它会自动生成另一个保持跟踪的布尔变量.但更难的部分是为每个单独的线程做一次.换句话说,它具有[ThreadStatic]行为.
这就是杀死你的原因,每个线程都有自己的SyncLock.这就是为什么你没有观察到同步的原因:)你需要将它移出方法并声明它Shared.