?
Solved

How to get data from IAsyncResult to a form?

Posted on 2011-09-16
6
Medium Priority
?
904 Views
Last Modified: 2013-11-08
I wrote a tcpClient that speaks to a server over a telnet connection.

The code below sends a packet (in this case, an authentication packet to login), and then does an asynchronus read to the callback.

Public Sub SendPacket(ByRef Packet As AMIPacket)
        Dim myWriteBuffer As NetworkStream = _session.GetStream
        If myWriteBuffer.CanWrite Then
            myWriteBuffer.BeginWrite(Packet.RenderPacket, 0, Packet.RenderPacket.Length, callBack, myWriteBuffer)
        End If
    End Sub

Open in new window


The problem is: the function that executes the asychnous operation parses the return information, which I need to pass to a textbox control on the form so I can log the communications. I get the error:


Cross-thread operation not valid: Control 'txtLog' accessed from a thread other than the thread it was created on.
A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll


How do I get the parsed data that is returned from the server passed to the form?
0
Comment
Question by:DrDamnit
6 Comments
 
LVL 36

Expert Comment

by:Miguel Oz
ID: 36552963
You need to interact with your GUI in a thread safe way, check:
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx

and look for the SetText method implementation.
0
 
LVL 4

Expert Comment

by:guramrit
ID: 36553052
Yo've posted incomplete information about code, or different code for different problem.
By the way BeginWrite doesn't return any value, but you can complete async operation using EndWrite(IAsyncResult).
And you can prevent cross thread errors to occur using txtLog.BeginInvoke function. If you need code then post your code where you pass value to a textbox control (txtLog).
0
 
LVL 13

Expert Comment

by:Corey Scheich
ID: 36553122
You need to invoke a delegate on the thread the control was created on, similar to below.

regards,

Corey

Public Sub Callback(ByVal ar As IAsyncResult)
        If TextBox1.InvokeRequired Then
            'create delegate
            Dim del As New AsyncCallback(AddressOf Callback)
            'invoke delegate on propper thread 
            TextBox1.BeginInvoke(del, New Object() {ar})
            Exit Sub
        Else
            'it is safe to update textbox if InvokeRequired returns false
            TextBox1.Text = ar.CompletedSynchronously
        End If
    End Sub

Open in new window

0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
LVL 32

Author Comment

by:DrDamnit
ID: 36557113
The code that is running in a separate thread (that apparently needs to be a delegate or delegated) is:

 
Public Function ProcessInboundPackets(ByVal ar As IAsyncResult) As Boolean
        Dim message(1024) As Byte
        Dim buffer(1024) As Byte
        Dim strBuffer As String
        Dim Response() As String
        Dim myNetworkStream As NetworkStream = CType(ar.AsyncState, NetworkStream)
        Dim i As Integer = 0
        Dim c As Integer = 0

        While myNetworkStream.CanRead
            ReDim buffer(1024)

            'Find the first null element in the message
            For i = 0 To message.Length
                If message(i) = 0 Then c = i
                Exit For
            Next
            'Get the inbound stream
            myNetworkStream.Read(buffer, 0, buffer.Length)

            'Copy bytes into the message until we get 13 10 13 10 or 0
            For i = 0 To buffer.Length - 1
                'Is there is enough room for a crlf crlf
                If i + 3 <= buffer.Length - 1 Then
                    'Is this the termination?
                    If buffer(i) = 13 And buffer(i + 1) = 10 And buffer(i + 2) = 13 And buffer(i + 3) = 10 Then
                        'we have reached the end. Write them to the message, and send the message for processing.
                        message(i + c) = buffer(i)
                        'Send the message for processing
                        strBuffer = "**********" & vbCrLf & System.Text.Encoding.UTF8.GetString(message).Trim & vbCrLf & "**********"
                        RaiseEvent Log(strBuffer)
                        'Check to see if we win.
                        Response = strBuffer.Split(":")
                        If Response(1) = "Authentication accepted" Then
                            Return True
                        Else
                            Return False
                        End If
                        'Reset the message buffer
                        ReDim message(1024)
                    Else
                        'This is not the end fo the message. Keep writing to the message buffer
                        message(i + c) = buffer(i)
                    End If
                End If
            Next

            'ShowPacket(buffer)
        End While

    End Function

Open in new window


This code runs in a class called clsAMI.vb. In order to pass the information back to the form, I am trying to use RaiseEvent() (see line 31), which is obviously failing.

How do I make this a delegate?

PS. The form code that fires for teh RaiseEvent() is this:

 
Private Sub AMI_Log(ByVal sMessage As String) Handles AMI.Log
        Dim strBuffer
        strBuffer = txtLog.Text
        strBuffer = strBuffer & vbCrLf & sMessage & vbCrLf
        Try
            txtLog.Text = strBuffer
        Catch ex As Exception
            Debug.Print(strBuffer)
            Debug.Print(ex.Message)
        End Try

        txtLog.SelectionStart = txtLog.Text.Length

    End Sub

Open in new window

0
 
LVL 13

Accepted Solution

by:
Corey Scheich earned 2000 total points
ID: 36557177
The attached code should do the trick.  You just have to declare a delegate with the same signature as the method you need it to delegate.

Corey
Delegate Sub AMI_LogDel (byval sMessage as string) 

Private Sub AMI_Log(ByVal sMessage As String) Handles AMI.Log
        
        If txtLog.InvokeRequired then
            'create delegate
            Dim del As New AMI_LogDel(AddressOf AMI_Log)
            'invoke delegate on propper thread 
            txtLog.BeginInvoke(del, New Object() {sMessage})
            Exit Sub
        else

        Dim strBuffer
        strBuffer = txtLog.Text
        strBuffer = strBuffer & vbCrLf & sMessage & vbCrLf
        Try
            txtLog.Text = strBuffer
        Catch ex As Exception
            Debug.Print(strBuffer)
            Debug.Print(ex.Message)
        End Try

        txtLog.SelectionStart = txtLog.Text.Length
       end if
    End Sub

Open in new window

0
 
LVL 32

Author Closing Comment

by:DrDamnit
ID: 36557467
So much simlier than I was making it! Thank You!
0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Native ability to set a user account password via AD GPO was removed because the passwords can be easily decrypted by any authenticated user in the domain. Microsoft recommends LAPS as a replacement and I have written an article that does something …
Enter Foreign and Special Characters Enter characters you can't find on a keyboard using its ASCII code ... and learn how to make a handy reference for yourself using Excel ~ Use these codes in any Windows application! ... whether it is a Micr…
Get the source code for a fully functional Access application shell with several popular security features that Access VBA application developers desire, but find difficult or impossible to figure out how to code. You get the source code for managi…
Suggested Courses
Course of the Month7 days, 2 hours left to enroll

594 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question