Question Multithreading: reading/setting variables, and passing variables.

vpvb

Member
Joined
Mar 8, 2011
Messages
6
Programming Experience
1-3
I've been reading a lot of documentation and have a few questions left unanswered. I've spent the past few hours searching for specific information and have had no luck; assistance would be welcomed.

Question 1:
What is the difference between "Background Worker" and "Worker Pool" as indicated within the MSDN samples provided.

Question 2:
I noticed while using, AddressOf _Function_, variables cannot be passed; what would be an efficient solution to this?

Question 3:
While using multithreading is it required to invoke before setting variables, or only form properties?

Question 4:
While using System.Net.Sockets is it safe/efficient to use Application.DoEvents while waiting for new data; or would be using a Do While loop be fine without DoEvents since the action would be multithreaded? Note: there can be up to 2000-3000 sockets in use at a time.

I have a lot more questions but for the time being these four are the most important with my current progress. I'm really new to the vb2010 transition so please don't assume I know terminology, thank you.
 
1. BackgroundWorker is a component (in Toolbox) that simplifies common multithreading usage for background tasks in forms environment. "Background Worker" could also be a common expression for a background task performed in a secondary thread, which probably then also is not a foreground thread.

The BackgroundWorker components DoWork handler is executed on a Threadpool thread. Threadpool is a managed pool of dynamically allocated background threads, that simplifies management of the number of concurrent threads, it also has initially a few idle threads ready to perform tasks which makes startup time faster, similarily for performance the thread count management allows waiting tasks to start immediately when a thread is available.

2. AddressOf is used when you create a delegate instance. The delegate can then be invoked, directly (delegate.BeginInvoke) or as parameter to Control.Invoke, to execute the method it points to. The delegate signature must match the method signature (actually the other way around...), so it can have parameters. Also BackgroundWorker component allows a parameter for the RunWorkerAsync method.

3. Control.Invoke is required to access controls not created in the calling thread. Controls are typically only created on the main UI thread. For variables that could be accessed from multiple threads simultaneously you have to implement other synchronization to prevent possible invalid object state, SyncLock statement is commonly used but there exist also other tools in System.Threading namespace for this.

4. DoEvents is used in UI thread to force the message loop to be processed when the UI thread is stilled busy doing code calls. It is not relevant for secondary threads. A loop in a secondary thread is fine, but beware it doesn't run too tight and pointlessly waste cpu resources, sometimes a Thread.Sleep makes sense to have the loop stall if there are not blocking calls.
 
Thank you for the help and quick response, I made use of the information provided.

While applying this information I ran into a problem, of which I wrote a detailed explanation of things I've tried; but my forum status became not logged in and the entire post was lost so I'll make this one brief.

Within a module
VB.NET:
    Private aSocket As New List(Of xyzSocket)
    Private Class xyzSocket
        Public Connected As Boolean
        Public theSocket As Socket
    End Class

    Private Sub InitiateConnection()

        With aSocket(SocketIndex)
[COLOR=red]            .theSocket.BeginConnect("192.168.1.1", 80, New AsyncCallback(AddressOf ConnectionResult), .theSocket)[/COLOR]
        End With
        'attempt connection
        SocketIndex += 1
        'raise

    End Sub

    Private Sub ConnectionResult(ByVal socketResult As IAsyncResult)
        MsgBox("im here")
        'dont know what to do here???
    End Sub

I'm having two problems...
1. The line in red is returning: Use the "new" keyword to create an object instance.
I've tried declaring .theSocket as New or = New in various places only resulting in more errors.

2. Even after getting the line in red working I suspect the SocketIndex variable won't be passed, leaving me unable to modify the List data.

I'm trying to make a program that uses multiple sockets. Every bit of documentation I find is only for single socket handling.
 
1. Socket Constructor (System.Net.Sockets)
2. the fourth parameter is the state object, where you are passing the socket instance. IAsyncResult Interface (System) AsyncState property contains this state value in callback, that you must use to call EndConnect on, incidently there is a code sample also that shows this Socket.EndConnect Method (System.Net.Sockets) All async Begin'Something' methods comes in pairs with End'Something' methods that must be called to complete the action started.
I'm trying to make a program that uses multiple sockets. Every bit of documentation I find is only for single socket handling.
If you can do one you can do any number of them. :)

If you don't have special requirements using TcpClient class is more convenient than Socket class.
 
Okay so unless I am mistaken this is how it all works...

When you issue a callback within the socket a handle (so to speak) is included. With that handle you can finish the connection, send data, get data, ect. Each socket should raise the callback with its own unique handle, and you just apply actions to that handle (IAsyncResult). Assuming I got that right, it makes sense to me now. However, I am still unsure how you associate a socket handle with a structure or class index.

Basically what I need to be able to do is connect a socket, and send socket specific data; such as a username or other miscellaneous information. This is what I mean by there are no examples showing such a thing. I understand you can create as many connections as you want but I'm unsure of how to tie specific data to them.
 
You could pass over the xyzSocket instance instead of its associated socket instance, if that is what you mean. The state object parameter can be used to pass any object.
 
I was having difficulties passing the class, this was tried...
VB.NET:
With aSocket(SocketIndex)
.theTCP.BeginConnect("192.168.1.1", 80, New AsyncCallback(AddressOf ConnectionResult), aSocket(SocketIndex))
End With
[COLOR=red]'while using the below the project would crash[/COLOR]
    Private Sub ConnectionResult(ByVal socketResult As IAsyncResult)
        Dim theClass As xyzSocket = CObj(socketResult)
        theClass.theTCP.EndConnect(theClass.theTCP)
    End Sub
Alternatively I tried the following...
VB.NET:
        With aSocket(SocketIndex)
                .ASyncResult = .theTCP.BeginConnect("192.168.1.1", 80, New AsyncCallback(AddressOf ConnectionResult), SocketIndex)
        End With

    Private Sub ConnectionResult(ByVal socketResult As IAsyncResult)
        Dim theIndex As Short = CShort(socketResult.AsyncState)
        With aSocket(theIndex)
            .theTCP.EndConnect(.ASyncResult)
            MsgBox("The Index: " & theIndex)
        End With
        'cleans up connection
    End Sub
and it seemed to of worked. I haven't tried sending or receiving data yet but I suspect if I've got this far the rest will be easy. As I said before I'm extremely new to vbNet but I would think passing a short would be better than copying an entire class. Unless you see something wrong with this I believe this will work for the project.

Thank you again for the persistent help.


Below is just the working code in the scenario someone stumbles upon this thread having the same problem..renamed a few things
VB.NET:
[COLOR=teal]'how to manage multiple asyncronized sockets while each socket has variables tied to it.[/COLOR]
[COLOR=olive]'in a module[/COLOR]
    Private aConnection As New List(Of xyzSocket)
    Private Class xyzSocket
        Public randomNumber As Single
        Public theTCP As TcpClient = New TcpClient
        Public ASyncResult As IAsyncResult
    End Class
    'holds socket data, my indexed (winsocks)

    Public Sub CreateSockets(ByRef SocketCount As Short)

        Dim arrIndex As Short
        For arrIndex = 0 To (SocketCount - 1)
            aConnection.Add(New xyzSocket)
        Next
        'create list of variable types
        SocketMax = (SocketCount - 1)
        'max index of sockets

    End Sub

    Public Sub ConnectSockets()

        Dim socketCount As Short

        For socketCount = 0 To SocketMax 'however many sockets you want
            InitiateConnection(socketCount)
        Next

    End Sub
 
    Private Sub InitiateConnection(ByRef SocketIndex As Short)
        With aConnection(SocketIndex)
             Try
                 .randomNumber= Rnd()
                 .ASyncResult = .theTCP.BeginConnect("192.168.1.1", 80, New AsyncCallback(AddressOf ConnectionResult), SocketIndex)
             Catch EX As Exception
                 MsgBox("-" & EX.Message)
             End Try
         End With
        'attempt connection

    End Sub

    Private Sub ConnectionResult(ByVal socketResult As IAsyncResult)
        Dim theIndex As Short = CShort(socketResult.AsyncState)
        With aConnection(theIndex)
            .theTCP.EndConnect(.ASyncResult)
             MsgBox("The Index: " & .randomNumber)
         End With
        'cleans up connection
    End Sub
 
Last edited:
'while using the below the project would crash
Private Sub ConnectionResult(ByVal socketResult As IAsyncResult)
Dim theClass As xyzSocket = CObj(socketResult)
The state object is still in the IAsyncResult.AsyncState property.
I would think passing a short would be better than copying an entire class.
It is only the reference that is passed, ie an integer representing the memory address of the object. It looks to me it would be simpler to pass that here to save you from having to manage a List.
A short is actually less efficient than an integer. Numeric Data Types (Visual Basic)
 
I changed the Short(s) to Integer(s). However, everything I read states ByVal was a copy, and ByRef was a reference; the callback sub will not take ByRef for whatever reason.
 
Classes are reference types, they are always passed by reference.
 
I didn't intend to take this long to get back to this thread but past few days have been a bit hectic. Thank you for all the help, although I believe I am going to scrap the project; I've been told the methods I have used were very inefficient, so I need to do more reading before attempting it again because efficiency is extremely important for this type of program. I have been able to apply what I learned to another small application though that is almost complete, so again thank you.
 
Back
Top