如何在不阻塞主线程的情况下实现UDP

时间:2019-11-01 16:23:28

标签: c# multithreading asynchronous udp

我正在使用的数据通过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();
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

await将通过调度方法的其余部分在给定任务继续之后运行来“阻止”当前方法。它有点类似(在语义上与Task.ContinueWith不同),因此csharp Console.WriteLine("Past The Async")仅在收到所有消息后才执行。

您不能通过“即发即弃”方式枚举单独任务上的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退出后立即终止,因此您实际上可能要等待,或者还有其他可以执行的工作。

答案 1 :(得分:1)

这是我用来使用异步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();
    }
}