Search code examples
vb.netasynccallbacksynclock

Why is SyncLock not working here?


I am working on a class library that will provide asynchronous communication to CLR applications.

There are asynchronous reads (BeginRead) on SslStream with a single callback routine shared by multiple streams. I don't want the callbacks to be processed in parallel during debugging, so I created a critical section:

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

To my surprise, that doesn't work, at least not when I set a breakpoint within the SyncLock block. Callbacks for multiple streams run within it at the same time, without waiting at the entry point until the previous thread has left it.

Single stepping it is a nightmare, especially when streams are being shut down (closed) simultaneously: execute line for stream 1, execute line for stream 2, execute next line for 1, execute next line for 2, and so on, through the entire block.

I thought maybe you need something more than just a generic "New Object", but then I saw there is at least one answer here on stack overflow that illustrates SyncLock exactly the way I am using it, with just "Static X as New Object" to create the synchronization object within the function that has to be locked.

Is it because the callback is actually coming from a win32 thread outside of the .Net framework that SyncLock doesn't work here?


Solution

  • I have never seen the usage of static local variables in VB before. That such a thing existed was news to me. I would suggest that you do it the conventional way instead and use a shared class variable.

    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