Как реализовать UDP без блокировки основного потока - PullRequest
0 голосов
/ 01 ноября 2019

Данные, которые я использую, поступают по 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 ]

1 голос
/ 01 ноября 2019

это основа программы, которую я использую для использования асинхронного 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();
    }
}
1 голос
/ 01 ноября 2019

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, так что вы, возможно, захотите подождать, или, возможно, у вас есть другая работа, которую вы можетевыполнять.

...