[RESOLVED] TCP Client responding to the main thread like Winsock
Hi, I have a user app written in VB which up till now has relied on winsock to connect to another device we have. The user app logs onto the device and then send / receives status reports from it which are used to set the controls on the apps forms.
This has all worked well for a long time but I'm now looking to move away from Winsock as I know it's not 'the right way' to do things and I also need to be able to send non ascii characters between the app and the device it's connected to (implementing multi language support).
The issue is with Winsock it would simply throw the DataArrival event when a message was received and I could then process the message and act upon it. When using a TcpClient socket connection I'm running into problems as all responses are on the socket thread which means I can't simply change controls on the main form without using the Invoke check.
What I want to be able to do is have the thread running the TcpClient simply alert the main form thread when it receives data and make that data available to the main thread so it can start processing it and triggering all the other functions etc required (these also interact with the Form). Whilst this is happening the TcpClient monitors any further messages and sends response messages as requested from the main thread.
All help with this would be greatly appreciated.
Re: TCP Client responding to the main thread like Winsock
A simple way to go is creating the listen thread on your main form, and setting Control.CheckForIllegalCrossThreadCalls property to false in your forms load event. I can't be bothered with the invokes either 8)
Re: TCP Client responding to the main thread like Winsock
Just cause you can't be bothered with invokes doesn't mean you shouldn't do them. It creates proper coding habits. Try not to spread habits like that DQ, it affects code quality and could cause problems in his program we may not expect. It's kind of why that Property exists.
You would setup a Do Loop on a separate thread (Look into Threading), which would constantly read the Stream. From there, you can use Invokes to pass the data back to the main thread which can process it. I would show you some code but I am at school right now.
Re: TCP Client responding to the main thread like Winsock
There is another alternative to invoke. You can store the synchronizationcontext of the main thread to a variable, then post calls to that context from the background thread. I do that in the UDP class that I have over in the networking forum (the name of the thread is odd, but if you search for threads started by me, and the word UDP, the thread with seven replies has the class in post #6). In that class, I post a call to a method that raises events. Since the call is posted to the UI context, the events are raised in the UI thread. You could do the same thing to run the TCP Client in the background, then raise whatever you want on the UI thread.
Re: TCP Client responding to the main thread like Winsock
Fair enough, formlessfellow has a point. Here's how to use invokes like he said:
Code:
Private Delegate Sub StringDelegate(ByVal Text As String)
Sub UpdateText(ByVal Text As String)
If Me.InvokeRequired = True Then
Me.Invoke(New StringDelegate(AddressOf UpdateText), Text)
Else
Me.Text = Text
End If
End Sub
Re: TCP Client responding to the main thread like Winsock
Thanks for all the suggestions so far. I guess some part of the problem is my lack of knowledge with invokes etc. My vb has tended to be learn what you need to know to get the job done at that time hence I have big gaps.
From the way formlesstree4 was saying I should be able to do what I want with an invoke from the do loop monitoring the read stream. As I already have the do loop monitoring the stream perhaps you can let me know how to get the invoke to hand data to a procedure and launch that procedure in the main thread. From looking around forums etc I thought invoke only applied to objects on a form. I've not seen examples of using them to launch procedures in different threads yet. Looking at DQ's example, that's just assigning the text to the open form isn't it, how would I then use it to launch something? The real issue is the text only has meaning to my app and comes in a variety of tab delimited lines stating control states ect so I don't need to show these to the user I just need to interpret them myself and then show the user what they need to see.
Shaggy, I will have a look at your example soon because I was trying something like this, at least with raising an event, but wasn't aware of the syncronizationcontext.
Re: TCP Client responding to the main thread like Winsock
Thanks for all the advice. I guess I'm not to familiar with the Invokes.
DQ, as my app initiates the connection and logs onto the device I've been using the TcpClient and that always appears to come up on it's own thread even if I launch it from the main thread.
Formless, I have got do loops monitoring the stream but I wasn't sure you could use invokes to pass data back to the main thread. All I've read on invokes appears to be form related and changing values of objects on there. If I can use an invoke to launch a stored procedure in the main thread that would solve my problem. Looking at DQ's example, isn't that simply updating the form text or am I missing something.
To clarify, the text I'm getting from the stream is lines of tab delimited values that I then use to set states on the form and for other things (populating dynamic controls etc) so I don't want to display the text but simply need to use it within a group of other procedures / functions that I would prefer to call from the main (UI) thread.
Shaggy, I haven't had a chance to look at your example yet but did try something similar with raising events with the exception that I wasn't aware of the synchronizationcontext so every time the new data event fired it still remained in the TcpClient thread rather than the UI thread. I'll give this a go.
Re: TCP Client responding to the main thread like Winsock
The synchronizationcontext solution is dead simple, but not easy to turn into a simple example, which is why I mentioned the class I have it used in. You basically create a variable to hold synchronization.Current, and set it to that while in the UI thread. You can then call the Post method on that variable to call a method in the UI thread. Doesn't get much easier than that. In my example, the method I call just raises events, but you could do whatever you wanted.
Re: TCP Client responding to the main thread like Winsock
If you follow the CodeBank link in my signature and check out my Asynchronous TCP thread, you'll find an example of using the asynchronous methods with a SynchronizationContext.
Re: TCP Client responding to the main thread like Winsock
Thanks all, the synchronizationcontext looks to do exactly what I need and, unless I'm missing something, has been relatively easy to use in a quick test project. Enjoy the weekend!