I didn’t know why I would need one either until the need came up (“Oh no, my UI is on a different thread!”). Delegates are described as similar to function pointers in C++ in the Microsoft documentation. When I read that I said to myself “yeah, but Visual Basic doesn’t work like that wonderful and painfully frustrating language that AT&T invented so long ago”. So Microsoft still has to learn that Chinese is painful if you’re not from China. I’m discovering in the new VB, it does kinda work like that – a little.
In my case I had a shared class and a form that were working together. My class raised an event that was handled on the form to update a control on the form. The event also had parameters that were passed with the event to the event handler on the form. When the handler was invoked I received an exception that stated the control I was accessing was on another thread. I didn’t have to deal with this in the old VB under ‘normal’ circumstances. If I did I would have to be the C++ programmer working in VB – and that would have been considered a work around at best. So this is vast new territory for me, and I apologize ahead of time if something isn’t perfect. And yes, its a Windows Forms project with no XAML.
So… How To
Conceptually, you have to create a Delegate (a function pointer in C++) for your method (yeah, the one that updates the control) that gets used (dereferenced and called) by the user control Invoke method which invokes the method (yeah, that one) on its thread. On an aside, don’t ask why I think Microsoft put a C++ programmer in charge of Visual Basic NET. However, I’m taking the bad with the good here – the new Thread way is really powerful in my opinion. I just really would have preferred this kind of ‘icky’ stuff to be abstracted away. I guess you can’t have that multi-thread evil at Microsoft with VB without a bit of ‘ick’. In other words, I can’t help but to be critical; it’s still kind of ‘hakish’ if you ask me.
OK, as I stated earlier, the event was handled on a form to update a control on the form. The first thing to do is to declare a Delegate at the top after the opening of the form class. The declaration is similar to an interface declaration in that there is no body to the declaration, just the function (or method) signature. Name the Delegate something like controlUpdateDelegate. Now go and code the controlUpdate method, which should be easy considering its probably the same code you wrote in your original handler. Now, in the original event handler, you’ll need to start an If block that tests for the control you’re updating InvokeRequired property (no autocomplete from the IDE unfortunately). If that boolean is true you have to create a New Delegate (updateControlDelegate) with the AddressOf the function you wrote to update the control (controlUpdate). After that you have to call that controls (the one you’re updating) Invoke method with the Delegate you created and the parameters you originally sent to the event handler. If that InvokeRequired boolean is false just call that method you created.
That’s it – that’s what worked for me.
Some Example Code Structure
' on the form is someControlPublic Class someForm Public Delegate Sub controlUpdateDelegate(someParam as String) Public Sub New() AddHandler someClass.coolEvent, AddressOf coolEventHappened someClass.doSomethingCool() End Sub Private Sub coolEventHappened(someParam As String) If someControl.InvokeRequired Then Dim del = New controlUpdateDelegate(AddressOf controlUpdate) someControl.Invoke(del, someParam) Else controlUpdate(someParam) End If End Sub Private Sub controlUpdate(someParam As String) ' update someControl here with someParam End Sub End Class Public Class someClass Public Shared Event coolEvent(someParam As String) Public Shared Sub doSomethingCool() RaiseEvent coolEvent("Cool!") End Sub End Class.