|
-
Apr 7th, 2007, 06:44 PM
#1
Thread Starter
Addicted Member
[RESOLVED] VB 2005 - Passing methods to a different thread.
I have a form with a text box and a list box. With the text box I can type in my information and pass the text_box.text data to the other thread with no problems and no delegates. If I select the EXACT same text data from the list box and pass the list_box.selecteditem to the other thread I get a threading error. Why does this happen and what do I need to do to fix it?
Thanks!
Last edited by tomroth; Apr 7th, 2007 at 07:29 PM.
Reason: Clarification
-
Apr 7th, 2007, 07:35 PM
#2
Re: VB 2005 - Passing methods to a different thread.
You should ALWAYS use delegation when accessing controls from worker threads. Some calls will work without it, some will appear to work but not, while others simply won't work. Do the right thing and use delegation EVERY time and you'll never have to work out which is which. Marshalling a method call to the thread that owns a control takes about 5 extra lines of code. That is not a big deal so trying to circumvent it is false economy.
-
Apr 7th, 2007, 07:45 PM
#3
Thread Starter
Addicted Member
Re: VB 2005 - Passing methods to a different thread.
I have no problem using a delegate, but the problem is that a list_box.text is called as a 'Public Overrrides Property Text() as String'. Delegate calls don't like this. How do I call the Delegate?
-
Apr 7th, 2007, 09:39 PM
#4
Re: VB 2005 - Passing methods to a different thread.
Huh? Whether a member is overridden or not makes no difference whatsoever to delegation. This code works exactly as you'd expect it to for any type of control:
vb Code:
Public Class Form1
Private Delegate Function GetControlTextCallback(ByVal ctl As Control) As String
Private Function GetControlText(ByVal ctl As Control) As String
Dim result As String
If ctl.InvokeRequired Then
result = CStr(ctl.Invoke(New GetControlTextCallback(AddressOf GetControlText), ctl))
Else
result = ctl.Text
End If
Return result
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.GetTextBoxAndListBoxText()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim t As New Threading.Thread(AddressOf GetTextBoxAndListBoxText)
t.Start()
End Sub
Private Sub GetTextBoxAndListBoxText()
MessageBox.Show("TextBox: " & Me.GetControlText(Me.TextBox1))
MessageBox.Show("ListBox: " & Me.GetControlText(Me.ListBox1))
End Sub
End Class
Try creating a new form, add a ListBox, a TextBox and two Buttons, then paste in that code and run it.
-
Apr 7th, 2007, 10:03 PM
#5
Thread Starter
Addicted Member
Re: VB 2005 - Passing methods to a different thread.
But if you hover over the method it is asking for a PROPERTY, not a Sub or Function. You can't put PROPERTY into a delegate call.
-
Apr 8th, 2007, 05:10 AM
#6
Re: VB 2005 - Passing methods to a different thread.
 Originally Posted by tomroth
But if you hover over the method it is asking for a PROPERTY, not a Sub or Function. You can't put PROPERTY into a delegate call.
Quite right, and nor did I try. You write a method that accesses the property of interest, just as in the code that I provided above.
-
Apr 9th, 2007, 01:28 PM
#7
Thread Starter
Addicted Member
Re: VB 2005 - Passing methods to a different thread.
I'm new to vb 2005, but I got your code to work somehow. I can follow the code but don't really understand how it accesses the list_box.selecteditem method. I'll try to understand it better.
Thanks for the help.
-
Apr 9th, 2007, 07:11 PM
#8
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
There is no ListBox.SelectedItem method. SelectedItem is a property, not a method, and my code doesn't access it at all. My code is simply an example of how you can access any control member via delegation. You could just as easily declare a method named GetListBoxSelectedItem with a ListBox argument and an Object return value:
vb Code:
Private Function GetListBoxSelectedItem(ByVal lbx As ListBox) As Object
Dim result As Object
If lbx.InvokeRequired Then
result = lbx.Invoke(New GetListBoxSelectedItemCallback(AddressOf GetListBoxSelectedItem), lbx)
Else
result = lbx.SelectedItem
End If
Return result
End Function
or you can write a similar function for a specific ListBox instance, e.g.
vb Code:
Private Function GetListBox1SelectedItem() As String
Dim result As String
If Me.ListBox1.InvokeRequired Then
result = CStr(Me.ListBox1.Invoke(New GetListBox1SelectedItemCallback(AddressOf GetListBox1SelectedItem)))
Else
result = CStr(Me.ListBox1.SelectedItem)
End If
Return result
End Function
You can tailor your method and the corresponding delegate (don't forget that the delegate must always have the same signature as the method) to any control and any member(s) of that control, be it property or method.
-
Apr 9th, 2007, 07:50 PM
#9
Thread Starter
Addicted Member
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
Ok. I'm sorry if I seem slow at understanding this. Would the last examples you gave work in a multi threaded app? I didn't see any delegates in the examples. You're right, .selecteditem is a PROPERTY, so when I declare the delegate, what signature am I following? I am doing this to better myself at work with no schooling and really having a handle on delegate calls seems to me will be very advantageous to my programming. I really appreciate your help with this. Also, methods, events, properties - I get them confused. Sorry.
Thanks again!!!
-
Apr 9th, 2007, 07:55 PM
#10
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
don't forget that the delegate must always have the same signature as the method
Here's the method signature from my first example:
vb Code:
Private Function GetControlText(ByVal ctl As Control) As String
and here's the corresponding delegate declaration:
vb Code:
Private Delegate Function GetControlTextCallback(ByVal ctl As Control) As String
Now here are the method signatures from my last examples:
vb Code:
Private Function GetListBoxSelectedItem(ByVal lbx As ListBox) As Object
vb Code:
Private Function GetListBox1SelectedItem() As String
so what do you suppose the delegate declarations should look like?
-
Apr 9th, 2007, 08:05 PM
#11
Thread Starter
Addicted Member
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
Private Delegate Function GetListBoxSelectedItem(byVal lbx as Listbox) As Object
Private Delegate Function GetListBoxSelectedItem() As String
So you're making your own methods as opposed to hovering over the control (hope control is correct) and waiting to see what VB tells you? If this is true I am guessing that this is a good intro into OOP? Yes?
Thanks again!!!
-
Apr 9th, 2007, 08:18 PM
#12
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
You can't have two members with the same name. Your method and delegate have to have different names, although it makes sense to use names that imply that they're linked. Notice in the first example my method is named "GetControlText" and my delegate is named "GetControlTextCallback".
-
Apr 9th, 2007, 08:28 PM
#13
Thread Starter
Addicted Member
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
Ohhhh. I see. No duplicate names. Also, from what I see that you are doing, if I delcare a method with something like "As Textbox" or "As Listbox" then does that give me access to all of the events and properties that the object has to offer?
-
Apr 9th, 2007, 09:11 PM
#14
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
The whole point of using delegation is because you can't access members of a control from a worker thread. There's no point having a method return a control because you're just in the same position that you started in: you can't access its members from a worker thread.
-
Apr 9th, 2007, 09:19 PM
#15
Thread Starter
Addicted Member
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
I understand that. I need to delegate. The signature of the delegate is what is escaping me. That's why I asked about declaring my own method to an object and writing the delegate to that method. The PROPERTY thing isn't liked by delegates and I saw you write a method that uses "...As Listbox) As Object". Is that giving me access to all of what Listbox has to offer?
-
Apr 9th, 2007, 09:28 PM
#16
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
That ListBox is the method argument. It's the ListBox whose member(s) you want to access. By doing that you are able to use a single method for multiple ListBoxes. You pass a ListBox to the method and it will use delegation to access the appropriate member(s) of that ListBox specifically. Pass a different ListBox and you'll access the same member(s) of that ListBox. That's why back in my first example I was able to declare the argument as type Control and then pass a TextBox and a ListBox to the same method. In each case it used delegation to get the Text property of that control.
If you only have one ListBox then there's no need to write a method that can handle multiple ListBoxes, so you can use a method written for a specific ListBox, just like my second example in post #8. That post contains two examples: the first can be used for multiple ListBox controls while the second is specifically for ListBox1.
-
Apr 9th, 2007, 09:37 PM
#17
Thread Starter
Addicted Member
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
But where did you access the .selecteditem member? The Listbox has lots of members and I didn't see the direct call to the .selecteditem? I'm sorry, be patient with me. I really am quite intelligent, it's just that the verbage gets very confusing and trying to put it all together is also a bit confusing. I do appreciate your help so very much.
Thanks!!!
-
Apr 9th, 2007, 09:40 PM
#18
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
-
Apr 9th, 2007, 09:51 PM
#19
Thread Starter
Addicted Member
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
So I could acces the .resetforecolor property, for example, using what you have written? If so, I don't get it! Where do you state which member or property you are looking for???
-
Apr 9th, 2007, 10:24 PM
#20
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
You said you wanted to access the SelectedItem property, so my code in post #8 accessed the SelectedItem property. If you don't want to access the SelectedItem property, but rather you want to access the ResetForeColor method then you would remove the reference to the SelectedItem property and...
Implementing delegation to access control members is very easy if you use these same steps every time.
1. Write a method to access the member(s) without delegation, e.g.
vb Code:
Private Sub ResetControlForeColor(ByVal ctl As Control)
ctl.ResetForeColor()
End Sub
Private Function GetListControlSelectedItem(ByVal lstCtl As ListControl) As Object
Return lstCtl.SelectedItem
End Function
2. If your methods have argumentsd or return values then declare a delegate with the same signature:
vb Code:
Private Delegate Sub ResetControlForeColorCallback(ByVal ctl As Control)
Private Delegate Function GetListControlSelectedItem(ByVal lstCtl As ListControl) As Object
Note that I simply added "Delegate" to the declarations, appended "Callback" to the names and removed the method bodies. If your methods don't have arguments and don't have return values then you don't need to declare your own delegate. You can just use the existing MethodInvoker delegate.
3. Now implement delegation in your methods. To do that you remove the existing body:
vb Code:
Private Sub ResetControlForeColor(ByVal ctl As Control)
End Sub
Private Function GetListControlSelectedItem(ByVal lstCtl As ListControl) As Object
End Function
then add the If block that tests whether delegation is required and implements it if it is:
vb Code:
Private Sub ResetControlForeColor(ByVal ctl As Control)
If ctl.InvokeRequired Then
ctl.Invoke(New ResetControlForeColorCallback(AddressOf ResetControlForeColor), ctl)
Else
End If
End Sub
Private Function GetListControlSelectedItem(ByVal lstCtl As ListControl) As Object
If lstCtl.InvokeRequired Then
Return lstCtl.Invoke(New GetListControlSelectedItemCallback(AddressOf GetListControlSelectedItem), lstCtl)
Else
End If
End Function
This part follows standard steps too. You test the InvokeRequired property of the control you want to access. If it's True then you're on a worker thread and delagation is required. Call the control's Invoke method and pass an instance of the corresponding delegate created with a reference to the current method. The remaining parameters to the Invoke method are the very same parameters that were passed to the current method.
4. Finally put your original method body back into the Else block:
vb Code:
Private Sub ResetControlForeColor(ByVal ctl As Control)
If ctl.InvokeRequired Then
ctl.Invoke(New ResetControlForeColorCallback(AddressOf ResetControlForeColor), ctl)
Else
ctl.ResetForeColor()
End If
End Sub
Private Function GetListControlSelectedItem(ByVal lstCtl As ListControl) As Object
If lstCtl.InvokeRequired Then
Return lstCtl.Invoke(New GetListControlSelectedItemCallback(AddressOf GetListControlSelectedItem), lstCtl)
Else
Return lstCtl.SelectedItem
End If
End Function
Last edited by jmcilhinney; Apr 9th, 2007 at 10:28 PM.
-
Apr 9th, 2007, 10:52 PM
#21
Thread Starter
Addicted Member
Re: [RESOLVED] VB 2005 - Passing methods to a different thread.
It's time for bed here in Michigan. Let me absorb this and get back to you. Thanks so very much for the detailed answers!!!
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|