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?
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