Reputation: 1672
I'm creating a thread that runs a UDP Client that receives a message, after it receives the message I want to close the UDP client and then end the thread, but I dont know how to end the thread since "Receive" always runs until it gets an answer.
This is my code so far:
private void RecieveChallenge()
{
UdpClient client = new UdpClient(26000);
IPEndPoint remoteIp = new IPEndPoint(IPAddress.Any, 0);
Byte[] receivedBytes = client.Receive(ref remoteIp);
string ipAddress = Encoding.ASCII.GetString(receivedBytes);
}
The important line is client.Receive(ref remoteIp);
Here is how I start my thread:
Thread recieveChallengeThread = new Thread(new ThreadStart(RecieveChallenge));
recieveDataThread.Start();
Upvotes: 8
Views: 15050
Reputation: 1
An improvement on Jacek's above solution uses a second while loop; doing so a time-out does not throw away a possible datagram that was being received at the moment a time-out fires (the original code calls for another ReceiveAsync on every time-out ignoring any ongoing Receive):
while (_monitoringThreadIsRunning {
var receiveTask = _udpClient.ReceiveAsync();
while (_monitoringThreadIsRunning {
var timeoutTask = Task.Delay(ReceiveTimeout);
if (timeoutTask == await Task.WhenAny(timeoutTask, receiveTask))
continue;
UdpReceiveResult udpReceiveResult = await receiveTask;
// handle udpReceiveResult.Buffer
break; // return to outer loop, launching another Receive
}
}
PS: I would have put this in a comment, however as it is my first contribution here, I was lacking the necessary reputation points to do so.
Upvotes: 0
Reputation: 505
I was looking for good answer and thanks to colleague advice I made following solution (seems to work fine)
while (_monitoringThreadIsRunning)
{
var timeoutTask = Task.Delay(ReceiveTimeout);
var receiveTask = _udpClient.ReceiveAsync();
if (timeoutTask == await Task.WhenAny(timeoutTask, receiveTask))
continue;
UdpReceiveResult udpReceiveResult = await receiveTask;
// handle udpReceiveResult.Buffer
}
For stopping you need to set _monitoringThreadIsRunning to false. It works without any exceptions.
Upvotes: 1
Reputation: 18965
client.Receive
will return an empty byte[]
when the connection is closed. You should just have to close the connection and change the provided code to:
private void RecieveChallenge()
{
UdpClient client = new UdpClient(26000);
IPEndPoint remoteIp = new IPEndPoint(IPAddress.Any, 0);
Byte[] receivedBytes = client.Receive(ref remoteIp);
if (receivedBytes == null || receivedBytes.Length == 0)
return;
string ipAddress = Encoding.ASCII.GetString(receivedBytes);
}
Though you'll probably want RecieveChallenge
to return a boolean indicating whether it is closed or not (of course ignoring the fact that your thread will only ever receive one message).
Upvotes: 8
Reputation: 4182
If you want to wait for it to end before continue on your current thread, you can use
recieveDataThread.Join();
Otherwise, thread closes as soon as the last line completes.
If you want to end it early, you can use
recieveDataThread.Abort();
from another thread.
Upvotes: 1
Reputation: 5980
Instead of Receive()
, you can use BeginReceive()
/EndReceive()
- it is an asynchronous alternative.
See MSDN: http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.beginreceive.aspx
These methods use a common APM (asynchronous programming model) of .NET.
Upvotes: 2