[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

Threading and Having a class update a form control Problem....

Posted on 2004-10-27
10
Medium Priority
?
444 Views
Last Modified: 2010-04-24
I have a function that is currently wrapped up in a Class so I can pass a
variable to it.

This function is going to be threaded out and I would like the class
function to be able to update a control on my form.  (Treeview).

Is this possible and how do I do it?


Here is a simplisitc overview of what I am doing...
Public Class Form1

Public Sub Button1_Click
   GetDirs()
end sub

Public Sub GetDirs()
        Dim dir As String
        Dim i As Integer = 1
        Dim dirs() As String = Directory.GetDirectories("P:\")
        For Each dir In dirs
            Dim t As System.Threading.Thread
            dim oListView as new SubClass1
            t = New System.Threading.Thread(AddressOf
oListView.FileListToListView)
            oListView.sFolder = dir
            '''' I thought by passing the Treeview1 control I could update
it in the class...
            oListView.tView = TreeView1
            t.Start()
            i += 1
            ProgressBar1.Value = 100 * (i / CLng(UBound(dirs)))
        Next
End Sub

end class

Public Class SubClass1
 Public sFolder as string
 public tView as treeview
 public sub FileListToListView
     '''' **** Here is where I want to update the Form1.treeview1 control
     tview.nodes.add(sFolder)
 end sub
end class

0
Comment
Question by:Rog D
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
10 Comments
 
LVL 6

Expert Comment

by:KGreg
ID: 12427145
The following code goes in your main form:

    Delegate Sub UpdateTreeviewHandler(ByVal sFolder As String)

    Private Sub UpdateTreeview_Callback(ByVal sFolder As String)
        If Me.InvokeRequired Then
            '*** switch over to primary UI thread
            Dim handler As New UpdateTreeviewHandler(AddressOf UpdateTreeview_Implementation)
            Dim args() As Object = {sFolder}
            Me.BeginInvoke(handler, args)
        Else
            '*** direct call - already running on primary UI thread
            UpdateUI_Implementation(sFolder)
        End If
    End Sub

    Private Sub UpdateTreeview_Implementation(ByVal sFolder As String)
        MyTreeview.Nodes.Add(sFolder)
        Application.DoEvents()
    End Sub

This next class will be the object that holds a delegate to the callback functions:

Public Class MyThreadClass
    Private delHandler As frmMain.UpdateTreeviewHandler

    Public Sub New(ByVal delHandler As frmMain.UpdateTreeviewHandler)
        Me.delHandler = delHandler
    End Sub

    Public Sub Process()
        '
        ' This is the code your thread performs..
        '
        delHandler.BeginInvoke(sFolder, Nothing, Nothing)
    End Sub
End Class


Finally,  on the form, do this to create the thread:

dim objThread as Threading.Thread
dim objProcess as new MyThreadClass(New UpdateTreeviewHandler(AddressOf UpdateTreeview_Callback)

objThread = New Threading.Thread(AddressOf objProcess.Process)


Hope this helps!

KGREG

0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 12427187
What your doing should work though.  Try throwing in a Refresh and DoEvents after you update the TreeView:

    tview.nodes.add(sFolder)
    tview.Refresh()
    Aplication.DoEvents()

~IM
0
 
LVL 6

Expert Comment

by:KGreg
ID: 12427190
Now, let me explain why this works.

You can't pass the treeview to the thread, because there is no way to pass it by reference.  The thread and the form that owns the treeview are two different processes in a sense.  What you can do, is pass a delegate object to a constructor of a class - which allows another object to invoke function calls on behalf of your form.

After that, all we have to do is start a thread based on our second object (which has the delegate object) and when the time comes to update the treeview, we invoke the delegate - which will call the function on the form.

0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 8

Author Comment

by:Rog D
ID: 12427465
kGreg,


This works great, but one problem is the application closes automatically when Run.  I am not calling anything to cause a close of application.  Any suggestions.  Do I need to have some clean up code when the threads are done?
I am very new to threading.

''  *** Here is where I call start the threads
Public Sub GetDirs()
        Dim dir As String
        Dim i As Integer = 1
        Dim dirs() As String = Directory.GetDirectories("P:\")
        ProgressBar1.Maximum = dirs.Length
        For Each dir In dirs
            Dim objThread As Threading.Thread
            Dim objProcess As New MyThreadClass(New UpdateTreeviewHandler(AddressOf UpdateTreeview_Callback))
            objThread = New Threading.Thread(AddressOf objProcess.Process)
            objProcess.sFolder = dir
            objThread.Name = dir
            objThread.Start()
            i += 1
            ProgressBar1.Value = ProgressBar1.Value + 1
        Next
    End Sub







'''''' ****  THis was added to the form code as explained above....

 Delegate Sub UpdateTreeviewHandler(ByVal sFolder As String)

    Private Sub UpdateTreeview_Callback(ByVal sFolder As String)
        If Me.InvokeRequired Then
            '*** switch over to primary UI thread
            Dim handler As New UpdateTreeviewHandler(AddressOf UpdateTreeview_Implementation)
            Dim args() As Object = {sFolder}
            Me.BeginInvoke(handler, args)
        Else
            '*** direct call - already running on primary UI thread
            UpdateTreeview_Implementation(sFolder)
        End If
    End Sub

    Private Sub UpdateTreeview_Implementation(ByVal sFolder As String)
        TreeView1.Nodes.Add(sFolder)
        Application.DoEvents()
    End Sub

''''' ***** This added to another class...


Public Class MyThreadClass
    Private delHandler As Form1.UpdateTreeviewHandler
    Public sFolder As String

    Public Sub New(ByVal delHandler As Form1.UpdateTreeviewHandler)
        Me.delHandler = delHandler
    End Sub

    Public Sub Process()
        '
        ' This is the code your thread performs..
        '
        delHandler.BeginInvoke(sFolder, Nothing, Nothing)
    End Sub
End Class
0
 
LVL 8

Author Comment

by:Rog D
ID: 12427811
Ok.  Program works fine when not running in IDE...

Now I have added 100 more points to someone who can help me now change the program above to add a node instead of a "String"

Meaning.  In the thread I am building a TreeNode with SubNodes and would like to add the Node with Subnodes to the tree.  I thought this would be easy change from what I asked before and it probably is.  






Thanks,

Rog
0
 
LVL 6

Accepted Solution

by:
KGreg earned 1400 total points
ID: 12485175
Here you go!


''''' ****  THis was added to the form code as explained above....

 Delegate Sub UpdateTreeviewHandler(ByVal objNode As TreeNode)

    Private Sub UpdateTreeview_Callback(ByVal objNode As TreeNode)
        If Me.InvokeRequired Then
            '*** switch over to primary UI thread
            Dim handler As New UpdateTreeviewHandler(AddressOf UpdateTreeview_Implementation)
            Dim args() As Object = {objNode}
            Me.BeginInvoke(handler, args)
        Else
            '*** direct call - already running on primary UI thread
            UpdateTreeview_Implementation(objNode)
        End If
    End Sub

    Private Sub UpdateTreeview_Implementation(ByVal objNode As TreeNode)
        TreeView1.Nodes.Add(objNode)
        Application.DoEvents()
    End Sub

''''' ***** This added to another class...


Public Class MyThreadClass
    Private delHandler As Form1.UpdateTreeviewHandler
    Public sFolder As String

    Public Sub New(ByVal delHandler As Form1.UpdateTreeviewHandler)
        Me.delHandler = delHandler
    End Sub

    Public Sub Process()
        '
        ' This is the code your thread performs..
        '
        delHandler.BeginInvoke((new System.Windows.Forms.TreeNode("MyTextForTheNode")), Nothing, Nothing)
    End Sub
End Class


Hope this helps!

KGREG
0
 
LVL 8

Author Comment

by:Rog D
ID: 12528342
KGreg,

One quick question...

What I am trying to do is fill several nodes with subnodes, then pass this parent node to the ui to be updated.

If possible what changes would need to be made in your code above to accomidate a node with subnodes rather than the "String" being passed?

Thanks,

Roger
0
 
LVL 6

Expert Comment

by:KGreg
ID: 12533205

I'm assuming the goal is to create a node, add a structure of sub-nodes, and pass the parent node to the UI so it can be added.  

All you need to do is build your node structure in the Process() procedure.  When the node has been built, invoke the delegate and pass in the node.  The UI will then add the node to the Nodes collection of the treeview and all will be well in Treeview land.

Here's the code:

''''' ****  THis was added to the form code as explained above....

 Delegate Sub UpdateTreeviewHandler(ByVal objNode As TreeNode)


    '  This is called when the delegate is invoked

    Private Sub UpdateTreeview_Callback(ByVal objNode As TreeNode)
        If Me.InvokeRequired Then
            '*** switch over to primary UI thread
            Dim handler As New UpdateTreeviewHandler(AddressOf UpdateTreeview_Implementation)
            Dim args() As Object = {objNode}
            Me.BeginInvoke(handler, args)
        Else
            '*** direct call - already running on primary UI thread
            UpdateTreeview_Implementation(objNode)
        End If
    End Sub

    '  This is called after the context is set to the UI by our delegate function
    '  It allows the UI to be updated..

    Private Sub UpdateTreeview_Implementation(ByVal objNode As TreeNode)
       
        '
        ' Add the node to the treeview..
        '

        TreeView1.Nodes.Add(objNode)
        Application.DoEvents()
    End Sub

''''' ***** This added to another class...


Public Class MyThreadClass
    Private delHandler As Form1.UpdateTreeviewHandler
    Public sFolder As String

    Public Sub New(ByVal delHandler As Form1.UpdateTreeviewHandler)
        Me.delHandler = delHandler
    End Sub

    Public Sub Process()
        '
        ' Create your node structure..
        '
        dim node as new TreeNode("Parent Node")

        node.Nodes.add(New TreeNode("Child Node")

        '  etc...

        '
        '  Invoke the delegate and pass in the node structure you've created..
        '
        delHandler.BeginInvoke(node, Nothing, Nothing)
    End Sub
End Class

Hope this helps,

KGREG
0
 
LVL 8

Author Comment

by:Rog D
ID: 12534316
Thanks...

Works great!
0
 
LVL 6

Expert Comment

by:KGreg
ID: 12534365
You're welcome!  I'm glad it worked for you

KGREG
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …
The ECB site provides FX rates for major currencies since its inception in 1999 in the form of an XML feed. The files have the following format (reducted for brevity) (CODE) There are three files available HERE (http://www.ecb.europa.eu/stats/exch…
Video by: ITPro.TV
In this episode Don builds upon the troubleshooting techniques by demonstrating how to properly monitor a vSphere deployment to detect problems before they occur. He begins the show using tools found within the vSphere suite as ends the show demonst…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …

656 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question