C# await udpClient.ReceiveAsync() 失败并终止程序

C# await udpClient.ReceiveAsync() fails and terminates program

我正在 运行使用 .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);
        }
    }

不确定调用方法,但根据给定的信息,我会建议以下 article,它具有 @Stephen Cleary

围绕异步等待的最佳实践

它说要避免 async void,我将文章的摘录粘贴到此处以供快速参考

  1. Async void methods can wreak havoc if the caller isn’t expecting them to be async. When the return type is Task, the caller knows it’s dealing with a future operation; when the return type is void, the caller might assume the method is complete by the time it returns. This problem can crop up in many unexpected ways.

    1. Exceptions from an Async Void Method Can’t Be Caught with Catch

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() { ... }