Vb.net 为什么SyncLock不在这里工作?

Vb.net 为什么SyncLock不在这里工作?,vb.net,asynccallback,synclock,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 = D

我正在开发一个类库,它将为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
令我惊讶的是,这不起作用,至少当我在SyncLock块中设置断点时是不起作用的。多个流的回调在其中同时运行,而无需在入口点等待前一个线程离开它

单步执行这是一场噩梦,尤其是当流同时被关闭(关闭)时:对流1执行行,对流2执行行,对1执行下一行,对2执行下一行,等等,贯穿整个块

我想也许你需要的不仅仅是一个普通的“新对象”,但是我看到这里至少有一个关于stack overflow的答案说明了SyncLock与我使用它的方式完全相同,只需使用“Static X as New Object”在必须锁定的函数中创建同步对象


是不是因为回调实际上来自.Net framework之外的win32线程,所以SyncLock在这里不起作用?

我以前从未在VB中见过使用
静态
局部变量。这种事情的存在对我来说是新闻。我建议您改用传统的方法,使用
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
Static关键字是困扰VB.NET实现者的一个相当沉重的负担。他们必须支持它,因为它在以前的Visual Basic版本中经常使用,省略它会给想要更新工具的程序员带来太多困难

但是它的遗留行为与线程非常不兼容,线程是.NET中非常受支持的特性。以前没有问题,因为旧的VB版本不支持创建线程。为该语句生成的MSIL代码量很大。您应该看看ildasm.exe实用程序

它之所以庞大是因为它需要做什么。它只在第一次输入方法时初始化变量一次。不太难,它会自动生成另一个跟踪的布尔变量。但更困难的部分是对每个线程执行一次。换句话说,它具有[ThreadStatic]行为


这就是你的致命之处,每个线程都有自己的同步锁。这就是为什么您根本没有观察到同步:)您需要将其移出方法并声明它
共享

该方法总是在同一对象上调用,还是通过该类型的单独对象调用?VB.NET不使用“静态”而使用共享。同时尝试将锁定对象移动到方法范围之外。@AllanS.Hansen这是不正确的。VB.NET确实允许对局部变量使用
Static
修饰符,就像VB6一样。@AllanS.Hansen在VB中确实存在,但对C#@JamesThorpe定义“正常”有不同的含义。它在这个上下文中的含义与在C中的相同上下文中的含义相同。Oops,当我将它移出函数时忘记将其共享。
    Static OneAtATime As New Object