VB.NET 在不浪费处理器使用的情况下侦听 TCP 连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22006872/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
VB.NET Listen for TCP connections without wasting processor usage
提问by asim-ishaq
I am creating a voice server with VB.NET using TCPListener. To check for incoming connections I have created an infinite loop in Form Load method and whenever a connection is available it accepts it and then creates a new thread to handle communication. Following is the code:
我正在使用 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
The server works perfectly and honor all connections but the problem is that the processor usage is always 100% because of this server whether any client is connected or not.Is there any better way to listen for incoming connections?
服务器运行完美并尊重所有连接,但问题是处理器使用率始终为 100%,因为该服务器无论是否连接了任何客户端。有没有更好的方法来监听传入的连接?
回答by Jon Skeet
Any time you find yourself reaching for Application.DoEvents, you should try to reconsider - it's generally a workaround. At least this time you already know you're in a bad situation :)
任何时候您发现自己正在寻求Application.DoEvents,您都应该尝试重新考虑 - 这通常是一种解决方法。至少这次你已经知道你的处境很糟糕:)
If you're happy to do everything synchronously, I would start up a new thread and then call TcpListener.AcceptTcpClientin that. (You couldcall TcpListener.AcceptSocketif you really want the socket, but TcpClientis usually a simpler way to go.) That call will block until there's a client ready anyway, so you don't need to loop round checking the Pendingproperty.
如果你愿意同步做所有事情,我会启动一个新线程,然后调用TcpListener.AcceptTcpClient它。(如果你真的想要这个套接字,你可以调用TcpListener.AcceptSocket,但TcpClient通常是一种更简单的方法。)该调用将阻塞,直到有一个客户端准备好了,所以你不需要循环检查Pending属性。
So you'll have your UI thread ready to receive UI events, and one thread waiting for inbound requests.
因此,您的 UI 线程将准备好接收 UI 事件,并且有一个线程等待入站请求。
Now, you coulduse the asynchronous API instead - especially if you're using VB11, with Async and Await. You could use:
现在,您可以改用异步 API - 特别是如果您使用 VB11,以及 Async 和 Await。你可以使用:
Dim client As TcpClient = Await listener.AcceptTcpClientAsync();
... in the UI thread. That won't block the UI thread, but will asynchronously startaccepting an incoming connection. When the connection is made, the rest of your async method will continue. You don't need the extra thread. You can potentially do allyour work on the UI thread, using asynchrony to avoid blocking. That will make it easier to interact with the UI, but it takes some getting used to.
...在 UI 线程中。这不会阻塞 UI 线程,但会异步开始接受传入连接。建立连接后,异步方法的其余部分将继续。你不需要额外的线程。您可以潜在地在 UI 线程上完成所有工作,使用异步来避免阻塞。这将使与 UI 交互更容易,但需要一些时间来适应。
If you're new to both asynchrony and networking, I'd probably startwith the synchronous version... there'll be less to get your head round. Then if you're feeling adventurous later on, you can convert everything to the asynchronous approach.
如果你对异步和网络都不熟悉,我可能会从同步版本开始……你的头脑会更少。然后,如果您以后喜欢冒险,您可以将所有内容转换为异步方法。
回答by user287848
I realize this is quite old, but in my searches for something similar, this was one of the first results.
我意识到这已经很老了,但在我搜索类似的东西时,这是第一个结果。
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
This is how I implemented TCPListener. I have about 0.1% usage on my FX-8350. I can't say for certain what it was like on my Athlon II X2 but it couldn't have been more than a few percent. The GUI won't freeze, and you shouldn't have any real CPU usage.
这就是我实现 TCPListener 的方式。我的 FX-8350 使用率约为 0.1%。我不能肯定地说我的 Athlon II X2 是什么样的,但它不可能超过百分之几。GUI 不会冻结,您不应该有任何真正的 CPU 使用率。
Of course, my actual implementation is in a couple different classes. This is a simple example of the base.
当然,我的实际实现是在几个不同的类中。这是基础的一个简单示例。

