VB.NET Event Handler as the producer of a multithreaded producer-consumer pattern

Home / Uncategorized / VB.NET Event Handler as the producer of a multithreaded producer-consumer pattern

Question:
The pattern below smells for a few reasons, but for the purposes of this question, let’s focus on the global variables and the event handler:Dim objectQueue As New BlockingCollection(Of Object)
Dim objectQueueCancel As New CancellationTokenSource

Sub Main()
Task.Run(Sub()
If Console.ReadKey.KeyChar() = "c" Then objectQueueCancel.Cancel()
End Sub)
Dim t1 As Task = Task.Run(Sub() NonBlockingConsumer())
Dim t2 As Task = Task.Run(Sub() NonBlockingProducer())
Task.WaitAll(t1, t2)
objectQueueCancel.Dispose()
Console.WriteLine("Press the Enter key to exit.")
Console.ReadLine()
End Sub

Private Sub NonBlockingProducer()
Dim sourceObjects As ICollection(Of Object) = Nothing ‘Sanitized for StackOverflow
For Each sourceObject In sourceObjects
If sourceObject.IsEnabled Then
Dim objectEventGenerator As New objectEventGenerator(sourceObject)
AddHandler objectEventGenerator.objectEvent, AddressOf Handler_ObjectEvent
objectEventGenerator.Enabled = True
End If
If objectQueue.IsAddingCompleted Then Exit For
Next sourceObject
End Sub

Public Sub Handler_ObjectEvent(ByVal sender As Object, ByVal e As objectEventArgs)
If Not objectQueue.IsAddingCompleted Then
If Not e.EventException Is Nothing Then
Environment.ExitCode = -1
Else
Dim itemToAdd As Object = Nothing
Dim itemQueued As Boolean = False
Do
Try
itemQueued = objectQueue.TryAdd(itemToAdd, 0, objectQueueCancel.Token) ‘TODO Tweak enqueue timeout
Catch ex As OperationCanceledException
objectQueue.CompleteAdding()
Exit Do
End Try
If itemQueued Then
itemToAdd = Nothing
Else
Thread.Sleep(0)
End If
Loop While Not itemQueued
End If
End If
End Sub

The only way of programmatically accessing the objects in the target use case is through an event listener, and while this code executes it has two pesky global variables. If I define / Dim the BlockingCollection and CancellationTokenSource in the Main() sub, I would have to pass them (I expect ByRef) into the event handler by way of NonBlockingProducer(). However, the event handler’s signature is fixed, i.e. I can’t simply extend it to be able to pass the variables in…

What is the "proper" way of refactoring this to eliminate the global variables?


Answer:

Read more

Leave a Reply

Your email address will not be published. Required fields are marked *