VB.NET侦听TCP连接而不浪费处理器使用率

时间:2014-02-25 06:58:24

标签: .net vb.net tcplistener

我正在使用TCPListener使用VB.NET创建语音服务器。为了检查传入连接,我在Form Load方法中创建了一个无限循环,并且只要有连接,它就会接受它,然后创建一个新线程来处理通信。以下是代码:

Private WithEvents SR As New SoundRecorder
Private TCPListener As TcpListener

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    TCPListener = New TcpListener(Net.IPAddress.Parse(GetIPv4Address), 2021)
    TCPListener.Start()
    While 1
        If TCPListener.Pending = True Then
            Dim voiceCom As New BroadcastSound(TCPListener.AcceptSocket())
            Dim th As New Threading.Thread(AddressOf voiceCom.startCommunication)
            th.Start()
        End If
        Application.DoEvents()
    End While
End Sub

服务器运行良好并且尊重所有连接但问题是处理器使用率总是100%因为此服务器是否连接了任何客户端。有没有更好的方法来监听传入连接?

2 个答案:

答案 0 :(得分:1)

每当你发现自己达到Application.DoEvents时,你应该尝试重新考虑 - 这通常是一种解决方法。至少这次你已经知道你处境不好:)

如果您愿意同步执行所有操作,我会启动一个新主题,然后在其中调用TcpListener.AcceptTcpClient。 (如果你真的想要套接字,你可以调用TcpListener.AcceptSocket,但TcpClient通常是一种更简单的方法。)该调用将阻塞,直到客户端准备就绪,所以你不需要循环检查Pending属性。

因此,您的UI线程已准备好接收UI事件,并且一个线程正在等待入站请求。

现在,你可以使用异步API - 特别是如果你使用VB11,使用Async和Await。你可以使用:

Dim client As TcpClient = Await listener.AcceptTcpClientAsync();

...在UI线程中。这不会阻止UI线程,但会异步启动接受传入连接。建立连接后,其余的异步方法将继续。你不需要额外的线程。您可以在UI线程上执行 all 您的工作,使用异步来避免阻塞。这样可以更容易地与UI进行交互,但需要一些时间来习惯。

如果你对异步和网络都不熟悉,我可能会用同步版本启动 ...这样你就可以更少了。然后,如果您以后有冒险精神,可以将所有内容转换为异步方法。

答案 1 :(得分:0)

我意识到这已经很老了,但在我搜索类似的东西时,这是最初的结果之一。

     Public Class main

        Private client As TcpClient
        Private listener As TcpListener
        Private WithEvents tcpBg As BackgroundWorker

        Private Sub main_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            tcpBg = New BackgroundWorker
            'Requires a routine that cancels background worker.
            tcpBg.WorkerSupportsCancellation = True
            'ip is most likely from a Textbox.
            Dim adr As Net.IPAddress = Net.IPAddress.Parse(ip)
            listener = New TcpListener(adr, 60000)

            tcpBg.RunWorkerAsync()
        End Sub     

        Private Sub tcpBg_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles tcpBg.DoWork
            listener.Start()
            While tcpBg.CancellationPending = False
                client = listener.AcceptTcpClient
                'Do something with your client.
                client.Close()
            End While
        End Sub

    End Class

这就是我实现TCPListener的方法。我的FX-8350使用率约为0.1%。我不能肯定地说我的Athlon II X2是什么样的,但它不可能超过百分之几。 GUI不会冻结,你不应该有任何真正的CPU使用。

当然,我的实际实现是在几个不同的类中。这是基础的一个简单例子。