Solved

How to get data from IAsyncResult to a form?

Posted on 2011-09-16
6
858 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 35

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:Corey2
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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:
Corey2 earned 500 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

939 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

Need Help in Real-Time?

Connect with top rated Experts

4 Experts available now in Live!

Get 1:1 Help Now