如何取消SendPingAsync

时间:2018-05-06 12:14:16

标签: c#

我有这段代码来检查服务器是否可用:

public static async Task<bool> PingServer()
{
    System.Net.NetworkInformation.Ping p1 = new System.Net.NetworkInformation.Ping();

    System.Net.NetworkInformation.PingReply PR = await p1.SendPingAsync("pc2");

    // check when the ping is not success
    if (PR.Status != System.Net.NetworkInformation.IPStatus.Success)
    {
        return false;
    }
    return true;
}

现在,我的问题是SendPingAsync不支持CancellationTokenSource,那么如何取消最后一次执行新ping以防止大量ping?

当服务器丢失时,PingServer()返回假值需要几秒钟。

这就是我致电PingServer()的方式:

var task = await PingServer();

if (task == true)
{
  //do some stuff like retrieve a table data from SQL server.
}

为什么我使用ping?因为当我想从SQL服务器获取一个表,如果服务器断开连接,我的app会输入一个断点。

public  async  static Task<System.Data.Linq.Table<Equipment>> GetEquipmentTable()
{  
   try
    {
        DataClassesDataContext dc = new DataClassesDataContext();
        // note : i tried so many ways to get table synchronize but it still freeze my UI ! 
        return await Task.Run(() => dc.GetTable<Equipment>());               
    }
    catch
    {
        return null;
    }
}
编辑:我使用ping通过从数据库中获取表来减少在制动模式下进入应用程序的机会。有没有其他方法来防止休息模式?在调用dc.GetTable()之前ping服务器的最佳方法是什么?

Break point

3 个答案:

答案 0 :(得分:3)

您是否考虑过使用超时参数?

From the documentation:

  

此重载允许您指定超时值   操作

如果这还不够,问题是ping调用是阻塞的,那么你可以在后台线程上执行它,前提是这是严格控制的。

答案 1 :(得分:1)

考虑

public static async Task<bool> PingServer() {
    using (var ping = new System.Net.NetworkInformation.Ping()) {
        try {
            var maxDelay = TimeSpan.FromSeconds(2); //Adjust as needed
            var tokenSource = new CancellationTokenSource(maxDelay);
            System.Net.NetworkInformation.PingReply PR = await Task.Run(() => 
                ping.SendPingAsync("pc2"), tokenSource.Token);
            // check when the ping is not success
            if (PR.Status != System.Net.NetworkInformation.IPStatus.Success) {
                return false;
            }
            return true;
        } catch {
            return false;
        }
    }
}

使用Task.Run使用取消令牌执行ping操作;如果ping结果在指定的时间之前返回,那么一切都很好。

将组件包装在using中以在退出函数时处理它。

答案 2 :(得分:1)

当您执行代码时,您所依赖的系统可能会失败,或者您的ping可能会立即关闭。

这就是为什么重试策略是一种更强大的方法,然后只需在调用之前ping一个系统。

以下是如何实施重试Cleanest way to write retry logic?

我会采用重试方法,但如果您仍想继续使用您的设计,那么

  • 安排定期任务以ping有问题的系统Is there a Task based replacement for System.Threading.Timer?
  • 确保将此定期任务安排在一个中心位置(应用程序启动等)
  • 从此定期任务中调出PingServer,并确保在设置Ping.SendAsync的情况下致电PingOptions.Timeout,请参阅this overload
  • PingServer设置某种共享状态,它可以是静态变量,也可以是Registry模式的实现
  • 确保您的共享状态是线程安全的
  • 您的其余代码可以调用此共享状态,以查明系统是否在线且可用

正如您所看到的,这种方法更为复杂,但您可以防止&#34;大量的ping&#34;到您依赖的系统