简体   繁体   English

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

[英]How to implement UDP without blocking main thread

The data I am using arrives by UDP.我使用的数据由 UDP 到达。 I want to create several UDP connections without blocking the main thread.我想在不阻塞主线程的情况下创建几个 UDP 连接。 I have implemented UDP connections synchronously and asynchronously, however they both keep the main thread locked.我已经同步和异步地实现了 UDP 连接,但是它们都保持主线程锁定。 My code never reaches 'Console.WriteLine("Past the Async")'我的代码永远不会到达'Console.WriteLine("Past the Async")'

The goal is to have the UDP connections running in the background.目标是让 UDP 连接在后台运行。

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?谁能提供一些关于下一步要尝试什么的方向,或者如何正确实现允许主线程仍然接收命令的 UDP 的异步版本?

I comment out ReceiveUdpData() for the async version.我注释掉异步版本的 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 will "block" the current method by scheduling the rest of the method to run after the given task continues. await将通过调度方法的 rest 在给定任务继续后运行来“阻止”当前方法。 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.它有点相似(在语义上与Task.ContinueWith ),因此csharp Console.WriteLine("Past The Async")仅在收到所有消息后才会执行。

You can not wait for the messages by enumerating the IAsyncEnumerable on a separate task in a "fire and forget" manner:您不能通过以“即发即弃”的方式在单独的任务上枚举 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);
   }
}

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.但是如果你这样做,你的程序将在Main退出后立即终止,所以你可能真的想等待,或者你可能还有其他一些可以执行的工作。

this a basis of program i am using to use an async udp:这是我用来使用异步 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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在不阻塞主线程的情况下等待回调 - How to wait for a callback without blocking main thread 如何在不阻塞主线程的情况下暂停 C# 代码执行? - How to Pause C# code execution without blocking main thread? 如何在不阻塞主线程的情况下返回异步HttpWebResponse? - How to return an async HttpWebResponse without blocking the main thread? 如何在不阻塞主线程的情况下调用异步函数同步? - How to call an async function synchronized without blocking the main thread? 对话框如何在不阻塞主线程的情况下阻止代码执行? - How do dialogs prevent code execution without blocking the main thread? 在不阻塞主线程的情况下等待一段时间 - Wait for a while without blocking main thread 如何以主要形式等待事件触发并在另一个线程中完成而不阻塞UI - How to wait in main form for an event fired and completed in another thread without blocking the UI 如何使用Thread.Sleep与Task.Run而不阻止主踏板 - How to use Thread.Sleep with Task.Run without blocking main tread 如何在不阻塞主UI线程的情况下等待事件处理程序返回值 - How to wait for a return value from an event handler without blocking main UI thread 如何在不阻塞主线程的情况下创建大量控件? - How can I create a large number of controls without blocking the Main Thread?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM