DrDamnit
asked on
How to get data from IAsyncResult to a form?
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.
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.InvalidOperationEx ception' occurred in System.Windows.Forms.dll
How do I get the parsed data that is returned from the server passed to the form?
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
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.InvalidOperationEx
How do I get the parsed data that is returned from the server passed to the form?
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).
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).
You need to invoke a delegate on the thread the control was created on, similar to below.
regards,
Corey
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
ASKER
The code that is running in a separate thread (that apparently needs to be a delegate or delegated) is:
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:
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
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
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
So much simlier than I was making it! Thank You!
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
and look for the SetText method implementation.