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:
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?
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 :)
If you're happy to do everything synchronously, I would start up a new thread and then call TcpListener.AcceptTcpClient
in that. (You could call TcpListener.AcceptSocket
if you really want the socket, but TcpClient
is 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 Pending
property.
So you'll have your UI thread ready to receive UI events, and one thread waiting for inbound requests.
Now, you could use the asynchronous API instead - especially if you're using VB11, with Async and Await. You could use:
Dim client As TcpClient = Await listener.AcceptTcpClientAsync();
... in the UI thread. That won't block the UI thread, but will asynchronously start accepting 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 all your 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.
If you're new to both asynchrony and networking, I'd probably start with 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.
See more on this question at Stackoverflow