我正在开发一个类库,它将为CLR应用程序提供异步通信。
在BeginRead上有异步读取( SslStream ),其中有一个由多个流共享的回调例程。我不希望在调试期间并行处理回调,因此我创建了一个关键部分:
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令我惊讶的是,这是行不通的,至少当我在SyncLock块中设置一个断点时是如此。多个流的回调同时在其中运行,而不需要在入口点等待直到前一个线程离开它。
单步执行特别是当流同时被关闭(关闭)时:流1执行行,流2执行行,1执行下一行,2执行下一行,等等。
我想您可能需要的不仅仅是一个通用的“新建对象”,但是我看到在堆栈溢出中至少有一个答案说明了我使用它的方式,只有“静态X作为新对象”在必须锁定的函数中创建同步对象。
是因为回调实际上来自.Net框架之外的一个.Net线程,SyncLock在这里不起作用吗?
发布于 2015-03-26 14:32:47
我以前从未见过在VB中使用static局部变量。这种事的存在对我来说是个新闻。我建议您使用传统的方法,使用shared类变量。
public Class Test
Private shared SyncRoot As Object = new Object()
Private Sub Callback_Read(ByVal ar As IAsyncResult)
SyncLock SyncRoot
Dim ThisSslStream As SslStream = DirectCast(ar.AsyncState, SslStream)
...
End SyncRoot
End Sub
End Class发布于 2015-03-26 15:09:45
Static OneAtATime As New Object静态关键字是VB.NET实现者脖子上相当沉重的磨石。他们必须支持它,因为它在以前的Visual版本中经常使用,忽略它会给想更新他们的工具的程序员带来太多的困难。
但是它的遗留行为与线程非常不兼容,这是.NET中非常支持的特性,以前没有问题,因为以前的VB版本不支持创建线程。为该语句生成的MSIL代码数量很大。您应该查看一下ildasm.exe实用程序。
它之所以庞大,是因为它需要做些什么。它只初始化变量一次,这是第一次输入该方法。不太难,它自动生成另一个布尔变量,以保持跟踪。但更困难的是,每一个线程都要做一次。换句话说,它具有ThreadStatic行为。
这就是在这里杀死你的原因,每个线程都有自己的SyncLock。这就是为什么您根本没有观察到同步:)您需要将它从方法中移出并声明为Shared。
https://stackoverflow.com/questions/29280314
复制相似问题