Question How to: Invoke a Delegate Method

RGM

Member
Joined
Nov 6, 2012
Messages
6
Programming Experience
Beginner
Hello all,

As I'm new (both to VB.net and the forum) my apologies upfront for not using the correct terms, I'm reading up as fast as I can but will need some help and guidance.

Now for the question: I'm trying to fill a TreeView in the background using the BackgroundWorker. My code worked as expected before moving it to the BackgroundWorker after which I immediately encountered the "Action being performed on this control is being called from the wrong thread...." error.

I used the guidance from the "How to; invoke a Delegate Method from: How to: Invoke a Delegate Method but can't get it to work. The "wrong thread" error has disappeared but instead my code now seems to "hang" at the actual adding of the TreeNode to the TreeView (line 11 of the code below:

FRM_BrowseRegistry.TV_Registry.Nodes.Add(NodeName)

I’m hoping somebody can point me in the right direction (again keeping in mind I’m a newbie at programming)

Thank you in advance, Ruud.

Imports Microsoft.Win32
 
Public Class FRM_BrowseRegistry
    'Create a Delegate
    Delegate Sub TV_RegistryAddNodeDelegate(ByVal NodeName As TreeNode)
 
    'Declare a class that contains a method with the same signature as the delegate
    Public Class ShowtreeNodeClass
 
        Sub ShowTreeNodeMethod(ByVal NodeName As TreeNode)
            FRM_BrowseRegistry.TV_Registry.Nodes.Add(NodeName)
        End Sub
 
    End Class
 
 
    Public Sub FRM_BrowseRegistry_Load(sender As Object, e As EventArgs) Handles MyBase.Load
 
        BackgroundWorker1.RunWorkerAsync()
 
    End Sub
 
    Public Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
 
        'Get registrykey for HKEY_CLASSES_ROOT'  
        Dim vRegKeyClassesRoot As RegistryKey = Registry.ClassesRoot
        'Create TreeNode and get its child nodes in CreateNodes method '  
        Dim ClassesRootParentNode As New TreeNode(vRegKeyClassesRoot.Name)
        ClassesRootParentNode = CreateNodes(ClassesRootParentNode, vRegKeyClassesRoot)
        'Show the node on treeview, use invoke as the treeview is updated from a background thread 
        Dim MyShowTreeNodeClass As New ShowtreeNodeClass
        'Create an instance of the delegate
        Dim MyShowTreeDelegate As TV_RegistryAddNodeDelegate = AddressOf MyShowTreeNodeClass.ShowTreeNodeMethod
        MyShowTreeDelegate.Invoke(ClassesRootParentNode)
 
    End Sub
 
    Private Function CreateNodes(ByVal vParentNode As TreeNode, ByVal vRegKey As RegistryKey) As TreeNode
 
        For Each vSubKeyName As String In vRegKey.GetSubKeyNames()
            Try
                ' Open subkey and create a childnode with subkeys name on it '  
                ' Then create childnodes for childnode '   
                Dim vSubKey As RegistryKey = vRegKey.OpenSubKey(vSubKeyName, False, Security.AccessControl.RegistryRights.ReadKey)
                Dim vChildNode As New TreeNode(vSubKey.Name)
                vChildNode = CreateNodes(vChildNode, vSubKey)
                vParentNode.Nodes.Add(vChildNode)
            Catch ex As Security.SecurityException
                ' Lots of security exceptions will be thrown if user is not admin or doesnt have access for whole registry '   
            Catch ex As Exception
            End Try
        Next
        Return vParentNode
 
    End Function
 
End Class 'FRM_BrowseRegistry


Update: On "post new thread" the code listing collapsed, new try.
 
Last edited by a moderator:
Pass ClassesRootParentNode over e.Result, handle RunWorkerCompleted event and get the result there. RunWorkerCompleted event is raised on UI thread and you can operate freely with the UI controls there without using control.Invoke.
 
Hi John,

Thank you for the quick answer (and the update to my message, now I understand how to display code properly) :tennis:

On your answer, I did that and yes that worked, as I ran in another issue I decided that I should learn how to use Control.Invoke anyway, hence the question. Since I've spent quite some time on it now and given that you propose this method I'll continue on the RunWorkerCompleted route for now.

Thank you!

BrR.
 
Control.Invoke is simple. You pass an instance of a delegate to it. That instance is a reference to a method you want to have called.
Traditionally you create the delegate instance by using the AddressOf operator, but lately you can also create delegates with lambda expressions - here's an example of that:
Dim node As New TreeNode("test")
Dim AddNode = Sub(n As TreeNode) Me.TreeView1.Nodes.Add(n)
Me.TreeView1.Invoke(AddNode, node)

AddNode is here a delegate instance, that points to the inline declared Sub method. Doing this saves us declaring the delegate explicitly, or using a delegate that is already declared elsewhere in .Net class library.
Next line invokes that delegate (indirectly calls the method the delegate refers to) and passes the node parameter to it.
 
Bloody hell..... that works.... :crushed: and is so much more elegant as what I was trying....

Thank you sir, you are a gentleman :smile:
 
Last edited:
Back
Top