-1

I'm a beginner in VB.NET, please bear with me.

I've downloaded a multiclient TCP-IP Socket Server-Client application in VB.NET. The Server listens pretty well, but the Client encounters below exception:

"Cross-thread operation not valid: Control 'txtIncomingText' accessed from a thread other than the thread it was created on."

I'll be greateful if you guys could help me with corrected version of the code. Thank you.

' ------- CLIENT CODE -------

Imports System.Windows.Forms
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading

Public Class frmClient

    Inherits Form

    Private Sub frmClient_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private _clientSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

    Public Sub New()
        InitializeComponent()
    End Sub

    Private receivedBuf As Byte() = New Byte(1023) {}
    Private thr As Thread

    Private Sub ReceiveData(ar As IAsyncResult)
        Dim socket As Socket = DirectCast(ar.AsyncState, Socket)
        Dim received As Integer = socket.EndReceive(ar)
        Dim dataBuf As Byte() = New Byte(received - 1) {}
        Array.Copy(receivedBuf, dataBuf, received)


        ' These two lines encounter an error ->>>>>
        txtIncomingText.Text = (Encoding.ASCII.GetString(dataBuf))
        rbChat.Text = "\nServer: " + txtIncomingText.Text


        _clientSocket.BeginReceive(receivedBuf, 0, receivedBuf.Length, SocketFlags.None, New AsyncCallback(AddressOf ReceiveData), _clientSocket)
    End Sub

    Private Sub SendLoop()
        While True
            'Console.WriteLine("Enter a request: ");
            'string req = Console.ReadLine();
            'byte[] buffer = Encoding.ASCII.GetBytes(req);
            '_clientSocket.Send(buffer);

            Dim receivedBuf As Byte() = New Byte(1023) {}
            Dim rev As Integer = _clientSocket.Receive(receivedBuf)
            If rev <> 0 Then
                Dim data As Byte() = New Byte(rev - 1) {}
                Array.Copy(receivedBuf, data, rev)
                lbStt.Text = ("Received: " + Encoding.ASCII.GetString(data))
                rbChat.AppendText(vbLf & "Server: " + Encoding.ASCII.GetString(data))
            Else
                _clientSocket.Close()
            End If
        End While
    End Sub

    Private Sub LoopConnect()
        Dim attempts As Integer = 0
        While Not _clientSocket.Connected
            Try
                attempts += 1
                _clientSocket.Connect(IPAddress.Loopback, 420)
            Catch generatedExceptionName As SocketException
                'Console.Clear();
                lbStt.Text = ("Connection attempts: " + attempts.ToString())
            End Try
        End While
        lbStt.Text = ("Connected!")
    End Sub

    Private Sub btnSend_Click(sender As System.Object, e As System.EventArgs) Handles btnSend.Click
        If _clientSocket.Connected Then

            Dim buffer As Byte() = Encoding.ASCII.GetBytes(txtText.Text)
            _clientSocket.Send(buffer)
            rbChat.AppendText("Client: " + txtText.Text)
        End If
    End Sub

    Private Sub btnConnect_Click(sender As System.Object, e As System.EventArgs) Handles btnConnect.Click
        LoopConnect()
        ' SendLoop();
        _clientSocket.BeginReceive(receivedBuf, 0, receivedBuf.Length, SocketFlags.None, New AsyncCallback(AddressOf ReceiveData), _clientSocket)            Dim buffer As Byte() = Encoding.ASCII.GetBytes("@@" + txtName.Text)
        _clientSocket.Send(buffer)
    End Sub

End Class
  • What part of the error message confuses you? it is very clear - you cannot access controls from a non UI thread. – Ňɏssa Pøngjǣrdenlarp Jun 01 '17 at 17:10
  • Possible duplicate of [Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on](https://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the) – Knowledge Cube Jun 01 '17 at 17:48
  • There must be a vb.net duplicate. – djv Jun 01 '17 at 17:58
  • @djv Not sure if there is, but they're both .NET languages, both happen for the same reason and both have similar fixes using delegate invocations. – Knowledge Cube Jun 01 '17 at 18:06
  • I agree 100%, but there are vb.net people who can't read c#. – djv Jun 01 '17 at 18:38
  • This solution is more general (and better) than my answer https://stackoverflow.com/a/1331055/832052. – djv Jun 01 '17 at 18:38

1 Answers1

2

Well, you should invoke the calls on the control's thread. This is a quick and dirty solution

Dim message = Encoding.ASCII.GetString(dataBuf)
txtIncomingText.Invoke(Sub() txtIncomingText.Text = message)
rbChat.Invoke(Sub() rbChat.Text = Environment.NewLine & "Server: " & message)

But you should check if invocation is required first. See https://msdn.microsoft.com/en-us/library/ms171728(v=vs.110).aspx

Also, "\n" is not how you make a new line in vb.net (did you copy this code from c#?).

And + is not how you concatenate strings in vb.net (see above parenthesis).

djv
  • 15,168
  • 7
  • 48
  • 72
  • Wow, thanks a lot!! It worked!! How do I upvote your answer? –  Jun 02 '17 at 01:02
  • You figured right, I downloaded, converted this code from C# to VB.NET using some conversion websites :) –  Jun 02 '17 at 01:03