【问题标题】:C# await udpClient.ReceiveAsync() fails and terminates programC# await udpClient.ReceiveAsync() 失败并终止程序
【发布时间】:2017-07-12 17:08:17
【问题描述】:

我正在使用 .NET 4.5.1 运行 C# 控制台应用程序。当我运行以下函数时,下面的 udpClient.ReceiveAsync() 调用会无声无息地终止程序。我该如何调试?

   public async void Run()
    {
        try
        {
            var armIpAddress = IPAddress.Parse("239.1.11.1");
            using (var udpClient = new UdpClient())
            {
                udpClient.ExclusiveAddressUse = false;
                var ipEndPoint = new IPEndPoint(IPAddress.Any, 12020);
                udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                udpClient.ExclusiveAddressUse = false;
                udpClient.Client.Bind(ipEndPoint);
                udpClient.JoinMulticastGroup(armIpAddress);

                while (true)
                {
                    var result = await udpClient.ReceiveAsync();
                    //...
                }
        }
        catch (Exception x)
        {
            Console.WriteLine(x.Message);
        }
    }

【问题讨论】:

  • 什么叫Run,为什么是async void 而不是async Task?这是无法追踪的主要来源。

标签: c# async-await udpclient


【解决方案1】:

await udpClient.ReceiveAsync() 的调用不会终止程序,也不会静默失败。

鉴于这种情况正在发生,我假设你有这样的事情:

public static void Main(string[] args)
{
    ...
    Run();
}

async void 方法中,一旦到达await 调用,控制就会返回给父级,因此程序的流程类似于:

public static void Main(string[] args)
{
    ...
    var armIpAddress = IPAddress.Parse("239.1.11.1");
    using (var udpClient = new UdpClient())
    {
        udpClient.ExclusiveAddressUse = false;
        .......

        while (true)
        {
            return; 
        }
    }
}

所以程序由于没有进一步的阻塞代码而结束。

要让它按预期工作,请将代码更改为:

public static void Main(string[] args)
{
    ...
    Run().Wait();
}

public async Task Run() { ... }

【讨论】:

    【解决方案2】:

    不确定调用方法,但根据给定的信息,我建议使用以下article @Stephen Cleary 提供的关于异步等待的最佳实践

    上面写着要避免async void,我在此处粘贴文章的摘录以供快速参考

    1. 如果调用者不希望它们是异步的,异步 void 方法可能会造成严重破坏。当返回类型为 Task 时,调用者知道它是 处理未来的操作;当返回类型为 void 时, 调用者可能会假设该方法在它返回时已经完成。 这个问题可能会以许多意想不到的方式出现。

      1. 不能用 Catch 捕获来自异步 Void 方法的异常

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      • 2018-03-11
      • 2011-09-18
      • 1970-01-01
      • 1970-01-01
      • 2016-11-10
      相关资源
      最近更新 更多