【问题标题】:C# Use async/await on UdpClient ReceiveC# 在 UdpClient 接收上使用 async/await
【发布时间】:2017-01-02 14:23:32
【问题描述】:

以下代码使用Task异步接收,并在控制台显示接收到的结果:

private void ReceiveMessage()
{
    Task.Run(async() => 
    {
         using(var udpClient = new UdpClient(15000))
         {
             while(true)
             {
                 var receivedResult = await udpClient.ReceiveAsync();
                 Console.Write(Encoding.ASCII.GetString(receivedResult.Buffer));
             }
         }
    });
}

我想学习如何使用 async/await 函数,所以我想知道如何使用 async/await 使函数 ReceiveMessage() 异步?

【问题讨论】:

  • 哪个“跟随功能”?
  • 我只看到一个有问题的函数...@RenéVogt
  • 我想你可能想给this一个阅读..

标签: c# asynchronous async-await udpclient


【解决方案1】:

如果您希望整个方法可以等待,只需将其更改为:

private async Task ReceiveMessage()
{
     using(var udpClient = new UdpClient(15000))
     {
         while(true)
         {
             var receivedResult = await udpClient.ReceiveAsync();
             Console.Write(Encoding.ASCII.GetString(receivedResult.Buffer));
         }
     }
}

您不再需要Task.Run(),它会使用线程。不需要那个线程。该方法现在在awaiting ReceiveAsync() 时返回给调用者。
ReceiveAsync() 完成时,该方法(最终)在Console.WriteLine() 处恢复。

【讨论】:

  • 实际上这段代码是正确的,但它并没有像你提到的那样使方法等待。你不能等待无效,你等待任务。
  • @Trickzter 很公平,我会解决的。
【解决方案2】:

如果您希望它在一个单独的线程上监听,那么您拥有的代码是有效的。如果你不想这样,我会删除 Task.Run 并确保在你的方法中返回 Task,如下所示:

private async Task ReceiveMessage()
{
    using (var udpClient = new UdpClient(15000))
    {
        while (true)
        {
            var receivedResult = await udpClient.ReceiveAsync();
            Console.Write(Encoding.ASCII.GetString(receivedResult.Buffer));
        }
    }
}

【讨论】:

    【解决方案3】:

    只需向您的函数添加另一个 async/await:

    private async void receiveMessage()
    {
        await Task.Run(async() => 
        {
             using(var udpClient = new UdpClient(15000))
             {
                 while(true)
                 {
                     var receivedResult = await udpClient.ReceiveAsync();
                     Console.Write(Encoding.ASCII.GetString(receivedResult.Buffer));
                 }
             }
        });
    }
    

    如果你想写一个等待的方法,返回一个任务:

    private Task foo(){
        Task doStuff = new Task(() => {});
        doStuff.Start();
        return doStuff;
    };
    
    //Another method
    private async void bar()
    {
        await foo();
    }
    

    更新: 如下所述,您实际上不需要在线程池内的线程上执行该任务。这没有错,但没用。为了更好地使用,您可以使用:

    private async void receiveMessage()
    {
         using(var udpClient = new UdpClient(15000))
         {
             while(true)
             {
                 var receivedResult = await udpClient.ReceiveAsync();
                 Console.Write(Encoding.ASCII.GetString(receivedResult.Buffer));
             }
         }
    }
    

    【讨论】:

    • Task.Run() 不必要地使用线程池中的线程。由于ReceiveAsync()已经是awaited,这是一种资源的浪费。
    • 完全正确,但不是这里讨论的重点。他只是要求一种使其异步工作的方法,而我刚刚完成了代码。但你是对的,先生。
    • SO 的目的是提供有助于未来读者的有用答案。当然,您回答了 OP 的直接问题,但即使是他也表示他想学习。将糟糕的代码展示为一个好例子有点味道。
    • @RenéVogt 同意。
    猜你喜欢
    • 1970-01-01
    • 2014-06-15
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多