|
-
Oct 26th, 2009, 04:46 AM
#1
Thread Starter
KING BODWAD XXI
Passing values between threads *Resolved*
Hello everyone, I am an old VB6 programmer and I am trying to get into vb.net but having an issue getting a variable value from a class library in a different thread.
What I am trying to do is create my own Winsock type control for my own use. Once data arrives I try and pass it back to the main application so that I can read it and process it.
So far I cant get it working at all. I have tried the following
Raiseevent
I try passing the value as a variable in the raiseevent property. This triggers an error about the value being in a different thread, I always thought that it would create a new variable in the thread of the application it was raising an event in and copy the value.
Function
I have tried writing a function into the class that I call (much like how the winsock control works) so that the class can return the value to the main application.
aka
strData = Myclass.GetData
in the class it returns the value and clears it from its own local variable. This however means the value returns to the main application as nothing even if I step through and see it assigning a value.
I have to be missing something really important. Coming from a VB6 background I dont really know where to begin.
Any help or pointers would be appreciated 
Thanks
Last edited by BodwadUK; Oct 28th, 2009 at 06:18 AM.
-
Oct 26th, 2009, 04:55 AM
#2
Addicted Member
Re: Passing values between threads
Maybe I'm missing something here... You would need to create a delegate and invoke it (others will correct me if I'm wrong I'm sure)
Last edited by 7777; Oct 26th, 2009 at 05:00 AM.
-
Oct 26th, 2009, 05:07 AM
#3
Re: Passing values between threads
but having an issue getting a variable value from a class library in a different thread.
What makes you think it is running in a different thread? Have you explicitly created a new thread in this class library?
Can you post the code you are using in your function (Myclass.GetData) and also the code around the part in your main application where you use this function?
PS if it is a threading issue, search for "worker threads" in the codebank on this forum and you will find a post from JMC that explains how to use delegates to invoke code on another thread
-
Oct 26th, 2009, 05:35 AM
#4
Thread Starter
KING BODWAD XXI
-
Oct 26th, 2009, 05:45 AM
#5
Re: Passing values between threads
OK well you have only uploaded the socket component you are making, not the actual application as well so I cant see how you are using your socket component or which function it is that you are having a problem with etc.
PS, just because something is in a different class library / project does NOT mean it is running in a different thread. The only time something runs in a different thread is if you either create a new Thread object and start your code via that, or if you use a method that uses multiple threads - I suspect the latter may be the case here as I notice you are using BeginConnect and BeginAccept etc, which are asynchronous methods.
EDIT: Also, do you know that JMC already made something like this just a few weeks ago? http://www.vbforums.com/showthread.php?t=587341
Last edited by chris128; Oct 26th, 2009 at 05:49 AM.
-
Oct 26th, 2009, 06:01 AM
#6
Addicted Member
Re: Passing values between threads
Something like this...
Code:
Line 20 Public Event DataArrived(byVal DataPacket As String)
Line 173 RaiseEvent DataArrived(DataPacket)
To use it
Code:
Private WithEvents listener As SLSock
Private Sub listener_DataArrived(byVal DataPacket As String) Handles listener.DataArrived
MessageBox.Show("Data Packet:" & DataPacket )
End Sub
-
Oct 26th, 2009, 06:12 AM
#7
Thread Starter
KING BODWAD XXI
Re: Passing values between threads
Bah sorry I must have the test program in a different folder. I will have a look at JMC's project and see if I can make sense of it. Thankyou
-
Oct 26th, 2009, 06:19 AM
#8
Thread Starter
KING BODWAD XXI
Re: Passing values between threads
Hi thanks 7777, thats what I tried to start with. The value gets passed in the event fine but I see now that the error occurs when I try to show the value in a text box on the form.
Is this where I should use the invoke command to display it in the textbox? I am struggling to understand why its in a different thread though as I thought the raiseevent would raise it in the thread of the application receiving the event (if that makes sense S)
It seems I have a lot to learn lol
I get this error on this raised event
Cross-thread operation not valid: Control 'txtServer' accessed from a thread other than the thread it was created on.
Code:
Private Sub tcpServer_DataArrived(ByVal strData As String) Handles tcpServer.DataArrived
'Send follow up command
tcpServer.SendData("Hello Client")
'Show the data
txtServer.Text = strData
End Sub
-
Oct 26th, 2009, 06:24 AM
#9
Re: Passing values between threads
No, RaiseEvent will raise the event in the thread that you call RaiseEvent in, not the thread that is handling the event. If you happen to handle that event on another thread then you need to invoke a delegate to execute the code on the correct thread.
-
Oct 26th, 2009, 06:40 AM
#10
Re: Passing values between threads
When you call RaiseEvent, the event is raised on the same thread and the event handlers are executed on the same thread. That means that if you call RaiseEvent on a secondary thread the event will be raised on that secondary thread and the event handlers will be executed on that secondary thread. As such, if you need to access controls from your event handler, you have two choices:
1. Marshal a method call to the UI thread first, then call RaiseEvent from that method.
2. Call RaiseEvent first, then marshal a method call to the UI thread in the event handler.
If you choose the first option then the objects handling the event, e.g. your form, need not even be aware that there was a secondary thread involved at all. If you choose the second option then the handling object must be aware of the multi-threading and account for it.
To marshal a method call from one thread to another, you have basically two choices: the ISynchronizeInvoke interface or the SynchronizationContext class. Despite the fact that many may not recognise the name, the ISynchronizeInvoke interface is the most familiar to most people. When we use the InvokeRequired property and Invoke or BeginInvoke methods of a control, that's actually an ISynchronizeInvoke implementation. For examples and an explanation of why and how to use the ISynchronizeInvoke interface to access controls from a secondary thread, follow the CodeBank link in my signature and find my Accessing Controls From Worker Threads submission. If you wanted raise events on a secondary thread and then marshal a method call to the UI thread in the event handler, that will show you how.
Examples of using the ISynchronizeInvoke interface before calling RaiseEvent, therefore raising the event on the UI thread, include the FileSystemWatcher and Timers.Timer classes. They both have a SynchronizingObject property of type ISynchronizeInvoke. If this property is not set then those classes will raise their events on background threads from the thread pool. If you assign a control to the property though, the events will be raised on the thread that owns that control's handle, using its ISynchronizeInvoke implementation. In that Asynchronous Client/Server submission of mine that chris128 mentioned, that's the approach that I took to begine with. I declared a SynchronisingObject property in my classes and, if set, it was used internally to marshal a call to the desired thread before calling RaiseEvent. I can post that version of the code here if you want to see it.
The reason that I would have to post it here is that I've replaced the attachment in that submission with a new version that uses the SynchronizationContext class. The SynchronisingObject property has been removed and all events are always raised on the same thread as the object was created on. You can check out the attachment in that submission to see how that works.
-
Oct 26th, 2009, 07:31 AM
#11
Addicted Member
Re: Passing values between threads
Here is a simple example of method # 2 as described above (you'll need to tweak it for your code of course). I would like to see an example of method # 1
Code:
Delegate Sub UpdateTextCallBack(ByVal vData As String)
Private Sub UpdateText(ByVal vData As String)
Try
If Me.TextBox2.InvokeRequired Then
Dim d As New UpdateTextCallBack(AddressOf UpdateText)
Me.Invoke(d, New Object() {vData})
Else
TextBox2.Text = vData
End If
Catch ex As Exception
End Try
End Sub
-
Oct 26th, 2009, 07:52 AM
#12
Re: Passing values between threads
 Originally Posted by 7777
I would like to see an example of method # 1
This is basically how I originally did it in my Async Client/Server:
vb.net Code:
Imports System.ComponentModel
Public Class EventRaiser
Private Delegate Sub EventRaiserInvoker(ByVal e As EventArgs)
Private _synchronisingObject As ISynchronizeInvoke
Public Property SynchronisingObject() As isynchronizeinvoke
Get
Return _synchronisingObject
End Get
Set(ByVal value As isynchronizeinvoke)
_synchronisingObject = value
End Set
End Property
Public Event SomeEvent As EventHandler
Protected Overridable Sub OnSomeEvent(ByVal e As EventArgs)
If Me._synchronisingObject IsNot Nothing AndAlso _
Me._synchronisingObject.InvokeRequired Then
Me._synchronisingObject.Invoke(New EventRaiserInvoker(AddressOf OnSomeEvent), _
New Object() {e})
Else
RaiseEvent SomeEvent(Me, e)
End If
End Sub
End Class
You would simply raise the event exactly as you would without the multi-threading support:
vb.net Code:
Me.OnSomeEvent(EventArgs.Empty)
-
Oct 28th, 2009, 06:17 AM
#13
Thread Starter
KING BODWAD XXI
Re: Passing values between threads
Hello, sorry about the late response been ill yesterday.
I have managed to get it working using the first method, I also now understand how it works which is great, before I was a little confused as to how it was executed etc but writting it into my application has made it much more clear.
Thanks for you help everyone
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
|