The data I am using arrives by UDP. I want to create several UDP connections without blocking the main thread. I have implemented UDP connections synchronously and asynchronously, however they both keep the main thread locked. My code never reaches 'Console.WriteLine("Past the Async")'
The goal is to have the UDP connections running in the background.
Can anyone provide some direction as to what to try next, or how to properly implement an async version of UDP that allows the main thread to still receive commands?
I comment out ReceiveUdpData() for the async version.
class Program
{
// The whole point of this is to not block the main thread.
static async Task Main(string[] args)
{
ReceiveUdpData();
Console.WriteLine("Past Receive UDP Data");
await foreach (var item in MessagesAsync())
{
Console.WriteLine(item);
}
Console.WriteLine("Past The Async");
}
// Synchronous connection to UDP.
public static void ReceiveUdpData()
{
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
var count = 0;
using (UdpClient client = new UdpClient(12345))
{
while (true)
{
Byte[] receiveBytes = client.Receive(ref remoteEndPoint);
count++;
Console.WriteLine(count);
}
}
}
// Async UDP connection
private static async IAsyncEnumerable<object> MessagesAsync()
{
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
var count = 0;
using (UdpClient client = new UdpClient(12345))
{
while (true)
{
UdpReceiveResult test = await client.ReceiveAsync();
count++;
yield return test.ToString();
}
}
}
}
await
will "block" the current method by scheduling the rest of the method to run after the given task continues. It's somewhat similar (not semantically identical to Task.ContinueWith
) so csharp Console.WriteLine("Past The Async")
will execute only after all the messages are received.
You can not wait for the messages by enumerating the IAsyncEnumerable on a separate task in a "fire and forget" manner:
static async Task Main(string[] args)
{
PrintMessages();
Console.WriteLine("Past The Async");
}
public static async Task PrintMessages()
{
await foreach (var item in MessagesAsync())
{
Console.WriteLine(item);
}
}
But if you do that, your program will terminate as soon as Main
exits, so you might actually want to wait, or maybe you have some other work you can perform.
this a basis of program i am using to use an async udp:
sample:
using System;
using System.Net.Sockets;
using System.Net;
class Program {
static void OnUpdateData(IAsyncResult result) {
UdpClient socket = result.AsyncState as UdpClient;
IPEndPoint source = new IPEndPoint(0, 0);
byte[] message = socket.EndReceive(result, ref source);
Console.WriteLine($"Received {message.Length} bytes from {source}");
// schedule the next receive operation once reading is done:
socket.BeginReceive(new AsyncCallback(OnUpdateData), socket);
}
static void Main(string[] args) {
UdpClient socket = new UdpClient(12345);
socket.BeginReceive(new AsyncCallback(OnUpdateData), socket);
//send message with same program or use another program
IPEndPoint target = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
// send a couple of sample messages:
for (int num = 1; num <= 3; num++) {
byte[] message = new byte[num];
socket.Send(message, message.Length, target);
}
Console.ReadKey();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.