none
如何让TCP监听不影响程序运行? RRS feed

  • 问题

  • 程序如下:

    Imports System.Net.Sockets
    Imports System.IO
    
    Public Class FormMain
    
        Private Sub ButtonTSListen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonTSListen.Click
    



    Dim TSListener As TcpListener Dim TSClient As TcpClient Dim TSStream As NetworkStream Dim TSReader As StreamReader Dim ReadMessage As String
    TSListener = New TcpListener(TextBoxTSPort.Text) TSListener.Start() TSClient = TSListener.AcceptTcpClient() TSStream = TSClient.GetStream() TSReader = New StreamReader(TSStream) While Not ReadMessage = "STOP" ReadMessage = TSReader.ReadLine() TextBoxTSWatch.Text = Now.ToString + vbCrLf + ReadMessage + vbCrLf + vbCrLf + TextBoxTSWatch.Text End While TSListener.Stop() TSClient.Close() TSStream.Close() TSReader.Close() End Sub End Class
    问题是:
    执行到 TSClient = TSListener.AcceptTcpClient() 的时候,程序就死住,等待tcp连接。
    执行到 TSStream = TSClient.GetStream() 的时候,又死住,等待接收数据。
    执行到 ReadMessage = TSReader.ReadLine() 的时候,死在那里等回车。
    而且,ButtonTSListen_Click 事件的代码结束之前,整个窗体不刷新。
    我想做成,一边接受数据,一边在 TextBoxTSWatch 里面显示出来。
    是不是要为监听单独建立一个线程?该怎样做?
    我自己试着做了一下,可是执行到为 TextBoxTSWatch.Text 赋值的时候,出错,提示不能跨线程调用控件......

    谁有比较好的解决方法?谢谢了先!
    2010年2月13日 6:51

答案

  • 这是你在另一个线程中调用控件的问题

    从线程访问textbox1时可以使用委托

    delegate Sub Settextbox1f(Str as string)'声明对象

    Sub SettextBox1(str as string)'访问textbox1
    if me.textbox1.InvokeRequired then
    Dim d as new Settextbox1f(AddressOf SettextBox1)
    me.invoke(d,new object(){str})
    else
    textbox1.text=str
    end sub


    调用的时候就用settextbox1(str)就可以了。

    http://blog.csdn.net/gh_li/archive/2009/02/06/3865740.aspx
    努力+方法=成功
    2010年2月22日 1:38
  • 你好!
         使用TcpListener的BeginAcceptTcpClient方法就可以实现"异步"接收了,无需等待,具体可以参考这个实例:
    ' Thread signal.
    Public Shared tcpClientConnected As New ManualResetEvent(False)
    
    
    ' Accept one client connection asynchronously.
    Public Shared Sub DoBeginAcceptTcpClient(listener As TcpListener)
       ' Set the event to nonsignaled state.
       tcpClientConnected.Reset()
       
       ' Start to listen for connections from a client.
       Console.WriteLine("Waiting for a connection...")
       
       ' Accept the connection. 
       ' BeginAcceptSocket() creates the accepted socket.
       listener.BeginAcceptTcpClient(New AsyncCallback(AddressOf DoAcceptTcpClientCallback), listener)
       
       ' Wait until a connection is made and processed before 
       ' continuing.
       tcpClientConnected.WaitOne()
    End Sub 'DoBeginAcceptTcpClient
    
    
    ' Process the client connection.
    Public Shared Sub DoAcceptTcpClientCallback(ar As IAsyncResult)
       ' Get the listener that handles the client request.
       Dim listener As TcpListener = CType(ar.AsyncState, TcpListener)
       
       ' End the operation and display the received data on 
       ' the console.
       Dim client As TcpClient = listener.EndAcceptTcpClient(ar)
       
       ' Process the connection here. (Add the client to a
       ' server table, read data, etc.)
       Console.WriteLine("Client connected completed")
       
       ' Signal the calling thread to continue.
       tcpClientConnected.Set()
    End Sub 'DoAcceptTcpClientCallback
     

    周雪峰
    2010年2月22日 2:46
    版主
  • “提示不能跨线程调用控件......” 这个可以通过设置 Control.CheckForIllegalCrossThreadCalls 属性为false解决
     不过建议采用以上提供的异步访问方法 

    Memory all alone in the moonlight~My Blog in .NET~~~
    2010年2月22日 7:10
    版主

全部回复

  • 这样子的提示:
    线程间操作无效: 从不是创建控件 "TextBoxTSWatch" 的线程访问它。

    2010年2月13日 7:13
  • 这是你在另一个线程中调用控件的问题

    从线程访问textbox1时可以使用委托

    delegate Sub Settextbox1f(Str as string)'声明对象

    Sub SettextBox1(str as string)'访问textbox1
    if me.textbox1.InvokeRequired then
    Dim d as new Settextbox1f(AddressOf SettextBox1)
    me.invoke(d,new object(){str})
    else
    textbox1.text=str
    end sub


    调用的时候就用settextbox1(str)就可以了。

    http://blog.csdn.net/gh_li/archive/2009/02/06/3865740.aspx
    努力+方法=成功
    2010年2月22日 1:38
  • 你好!
         使用TcpListener的BeginAcceptTcpClient方法就可以实现"异步"接收了,无需等待,具体可以参考这个实例:
    ' Thread signal.
    Public Shared tcpClientConnected As New ManualResetEvent(False)
    
    
    ' Accept one client connection asynchronously.
    Public Shared Sub DoBeginAcceptTcpClient(listener As TcpListener)
       ' Set the event to nonsignaled state.
       tcpClientConnected.Reset()
       
       ' Start to listen for connections from a client.
       Console.WriteLine("Waiting for a connection...")
       
       ' Accept the connection. 
       ' BeginAcceptSocket() creates the accepted socket.
       listener.BeginAcceptTcpClient(New AsyncCallback(AddressOf DoAcceptTcpClientCallback), listener)
       
       ' Wait until a connection is made and processed before 
       ' continuing.
       tcpClientConnected.WaitOne()
    End Sub 'DoBeginAcceptTcpClient
    
    
    ' Process the client connection.
    Public Shared Sub DoAcceptTcpClientCallback(ar As IAsyncResult)
       ' Get the listener that handles the client request.
       Dim listener As TcpListener = CType(ar.AsyncState, TcpListener)
       
       ' End the operation and display the received data on 
       ' the console.
       Dim client As TcpClient = listener.EndAcceptTcpClient(ar)
       
       ' Process the connection here. (Add the client to a
       ' server table, read data, etc.)
       Console.WriteLine("Client connected completed")
       
       ' Signal the calling thread to continue.
       tcpClientConnected.Set()
    End Sub 'DoAcceptTcpClientCallback
     

    周雪峰
    2010年2月22日 2:46
    版主
  • “提示不能跨线程调用控件......” 这个可以通过设置 Control.CheckForIllegalCrossThreadCalls 属性为false解决
     不过建议采用以上提供的异步访问方法 

    Memory all alone in the moonlight~My Blog in .NET~~~
    2010年2月22日 7:10
    版主
  • 前几天宽带到期了,过年期间没去续费,所以今天才看到回复...

    问题已经解决了,感谢诸位的解答!
    2010年2月25日 5:11