Click here to Skip to main content
16,020,313 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I have exhausted my time, strength, energy, and searches to find a solution to what I am attempting to do. Now I ask for help days later :).

I have created a class for Socket reads so I can create sockets on command. Due to performing a socket read, the program will freeze waiting for incoming data due to being on a single thread. So I created a separate thread for the reading of the sock and attempt to invoke an event to prevent multi-threading errors.

But I am getting an error when trying to Invoke: "Invoke or BeginInvoke cannot be called on a control until the window handle has been created."

How can I fix this or is there a better way to read a sock without freezing the thread?


Class for Sockets:
VB
Option Explicit On
Option Strict On

Imports System.Text
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading

Public Class clsSock
    Inherits Control

    Private Sock As Socket
    Private sName As String, sHost As String, sPort As Integer, sConnected As Boolean

    Public Event Connected(ByVal sockname As String)
    Public Event Read(ByVal sockname As String, ByVal sockread As String)

    Delegate Sub onRead(ByVal msg As String)
    Private _onRead As onRead

    Dim tdReadSock As Thread

    Public Sub New()
        _onRead = New onRead(AddressOf RaiseRead)
    End Sub

    Public Sub Open(ByVal name As String, ByVal host As String, ByVal port As Integer)
        'define endpoint, connect socket
        Dim ipHost As IPHostEntry = Dns.GetHostEntry(host)
        Dim ipEnd As New IPEndPoint(ipHost.AddressList(0), port)
        Sock = New Socket(ipEnd.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
        Sock.Connect(ipEnd)

        'assign local variables
        sName = name
        sHost = host
        sPort = port
        sConnected = True

        'raise an event for connection success
        RaiseEvent Connected(name)

        'start new thread for socket reading to prevent application freezing from STA
        tdReadSock = New Thread(New ThreadStart(AddressOf sockMonitor))
        tdReadSock.Start()
    End Sub

    Public Sub Send(ByVal sockdata As String)
        Dim data() As Byte = ASCIIEncoding.UTF8.GetBytes(sockdata & vbCrLf)
        Sock.Send(data, data.Length, SocketFlags.None)
    End Sub

    Private Sub sockMonitor()
        'loop while sock is connected, wait for receive, raise event for read
        Do While Sock.Connected = True
            Dim data(4096) As Byte

            Sock.Receive(data)
            Dim msg As String, msgs() As String = ASCIIEncoding.UTF8.GetString(data).Trim(Chr(0)).Split(CChar(vbCrLf))

            For Each msg In msgs
                If msg.Length > 0 Then BeginInvoke(_onRead, New Object() {msg})
            Next
        Loop
    End Sub

    Private Sub RaiseRead(ByVal msg As String)
        RaiseEvent Read(sName, msg)
    End Sub
End Class



Code for calling:

VB
Private WithEvents Socks As clsSock

Private Sub Sock_Connected(ByVal state As String) Handles Socks.Connected
    MsgBox("Connected - " & state)
    Socks.Send("/GET etc etc etc")
End Sub
Private Sub Sock_Read(ByVal sockname As String, ByVal sockread As String) Handles Socks.Read
    Text1.AppendText(sockname & " - " & sockread & vbCrLf)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Socks = New clsSock()
    Socks.Open("google", "google.com", 80)
End Sub


Any help would be great.
Posted

1 solution

You control has to be a control, a part of your UI to use invocation. You need to insert is into some other control which is already a part of your form and UI.

You don't seem to understand the use of Invoke/BeginInvoke. This is not "to prevent multi-threading errors" (what mysterious errors did you mean?!) but to call some delegates using UI on UI thread. The delegates and call parameters are put to queue; and this queue is used by the UI thread for actual calls.

See my Answers to some previous Questions for more detail:
Control.Invoke() vs. Control.BeginInvoke()[^]
Problem with Treeview Scanner And MD5[^]
Multple clients from same port Number[^]

From these reference, you will find my design sketched on typical use of threading. If you understand this, you should doubt about a way you're trying to use you control. You should re-design it. Why doing socket operation in control? You should couple UI with you thread loosely (http://en.wikipedia.org/wiki/Loose_coupling[^]) and isolate UI from functionality very thoroughly. You need to have one or two threads (depending on client or server side, see my references above, the Answers about networking) for your networking and invoke UI methods from a thread.

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900