You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Mac中Ping.SendPingAsync获取的往返时间与终端结果不符的问题排查及解决方案咨询

解决Xamarin.Mac中Ping.SendPingAsync返回延迟偏高的问题

我之前在做Xamarin.Mac项目时也遇到过一模一样的问题——用.NET的Ping.SendPingAsync拿到的往返时间总是比终端的ping命令慢不少,Windows上却完全正常。结合你的环境(Xamarin.Mac 6.20.2、.NET Framework 4.8、Mono 6.12.0.93、macOS Catalina 10.15.2),咱们来一步步解决这个问题:

问题根源

这个差异主要来自Mono对Ping API的macOS实现:.NET的Ping类在macOS上是基于Mono的封装,底层调用系统API时会额外引入线程调度、对象初始化的开销;而终端的ping是原生系统工具,直接和网络栈交互,效率更高,所以延迟结果更准确。

解决方案

方案1:调用系统原生ping命令并解析输出(推荐,和终端结果完全一致)

既然终端的ping结果是准确的,我们可以直接在代码里调用系统的ping命令,捕获输出后解析出往返时间。这种方式完全绕过Mono的Ping封装,结果和你在终端看到的完全一致。

示例代码:

private async Task NativePingAsync()
{
    for (int i = 0; i < 100; i++)
    {
        try
        {
            // macOS的ping命令:-c 1 表示发送1个包,-W 1表示超时1秒(单位秒)
            var processStartInfo = new ProcessStartInfo
            {
                FileName = "/sbin/ping",
                Arguments = "-c 1 -W 1 google.com",
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using (var process = Process.Start(processStartInfo))
            {
                await process.WaitForExitAsync();
                var output = await process.StandardOutput.ReadToEndAsync();
                
                // 解析输出中的time值,比如匹配 "time=54.082 ms" 这样的字符串
                var match = System.Text.RegularExpressions.Regex.Match(output, @"time=(\d+\.\d+) ms");
                if (match.Success)
                {
                    if (double.TryParse(match.Groups[1].Value, out var roundtripTime))
                    {
                        Console.WriteLine($"RoundTrip time: {roundtripTime} ms");
                    }
                }
                else
                {
                    Console.WriteLine("Failed to get ping details");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Ping failed: {ex.Message}");
        }
        await Task.Delay(1000);
    }
}

方案2:优化现有Ping.SendPingAsync的使用(减少部分延迟)

如果不想调用系统命令,可以优化现有代码——你当前每次循环都新建Ping对象,这会带来额外的初始化开销。复用同一个Ping实例能减少这部分延迟,让结果更接近终端值:

示例代码:

private async Task OptimizedPingAsync()
{
    // 把Ping实例移到循环外面,复用
    using (var ping = new Ping())
    {
        for (int i = 0; i < 100; i++)
        {
            try
            {
                PingReply reply = await ping.SendPingAsync("google.com", 500);
                if (reply.Status == IPStatus.Success)
                {
                    Console.WriteLine("Address: {0}", reply.Address.ToString());
                    Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
                }
                else
                {
                    Console.WriteLine("Failed to get ping details");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Ping failed: {ex.Message}");
            }
            await Task.Delay(1000);
        }
    }
}

效果说明

  • 方案1的结果会和你在终端执行ping google.com的结果完全一致,因为用的是同一个原生工具;
  • 方案2能减少大约10-15ms的额外开销,但可能还是会和终端有微小差距,毕竟还是基于Mono的封装。

内容的提问来源于stack exchange,提问作者Mr.Tin Tin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 07:07:45