如何在不阻塞主线程的情况下实现UDP
How to implement UDP without blocking main thread
我使用的数据是通过UDP到达的。我想在不阻塞主线程的情况下创建多个 UDP 连接。我已经实现了同步和异步的 UDP 连接,但是它们都保持主线程锁定。我的代码从未达到 'Console.WriteLine("Past the Async")'
目标是在后台建立 UDP 连接 运行。
任何人都可以提供一些关于下一步尝试的方向,或者如何正确实现允许主线程仍然接收命令的异步版本的 UDP 吗?
我注释掉了异步版本的 ReceiveUdpData()。
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
将 "block" 当前方法,方法是在给定任务继续后将方法的其余部分调度到 运行。它有点相似(在语义上与 Task.ContinueWith
不同)所以 csharp Console.WriteLine("Past The Async")
将仅在收到所有消息后执行。
您不能通过以 "fire and forget" 方式在单独的任务上枚举 IAsyncEnumerable 来等待消息:
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);
}
}
但如果你这样做,你的程序将在 Main
退出后立即终止,所以你可能真的想等待,或者你有其他可以执行的工作。
这是我用来使用异步 udp 的程序的基础:
示例:
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();
}
}
我使用的数据是通过UDP到达的。我想在不阻塞主线程的情况下创建多个 UDP 连接。我已经实现了同步和异步的 UDP 连接,但是它们都保持主线程锁定。我的代码从未达到 'Console.WriteLine("Past the Async")'
目标是在后台建立 UDP 连接 运行。
任何人都可以提供一些关于下一步尝试的方向,或者如何正确实现允许主线程仍然接收命令的异步版本的 UDP 吗?
我注释掉了异步版本的 ReceiveUdpData()。
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
将 "block" 当前方法,方法是在给定任务继续后将方法的其余部分调度到 运行。它有点相似(在语义上与 Task.ContinueWith
不同)所以 csharp Console.WriteLine("Past The Async")
将仅在收到所有消息后执行。
您不能通过以 "fire and forget" 方式在单独的任务上枚举 IAsyncEnumerable 来等待消息:
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);
}
}
但如果你这样做,你的程序将在 Main
退出后立即终止,所以你可能真的想等待,或者你有其他可以执行的工作。
这是我用来使用异步 udp 的程序的基础:
示例:
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();
}
}