Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How to get data from IAsyncResult to a form?

Posted on 2011-09-16
6
Medium Priority
?
892 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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: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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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 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

Monthly Recap

May was a big month for new releases from Linux Academy! Take a look at what our team built recently in our blog. You can access the newest releases from our blog.

Question has a verified solution.

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

In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …

704 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