簡體   English   中英

如何在不阻塞主線程的情況下實現 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將通過調度方法的 rest 在給定任務繼續后運行來“阻止”當前方法。 它有點相似(在語義上與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退出后立即終止,所以你可能真的想等待,或者你可能還有其他一些可以執行的工作。

這是我用來使用異步 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();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM