Mamad
Mamad

Reputation: 454

How to cancel SendPingAsync

I have this code to check if Server is available or not:

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;
}

Now, my problem is that SendPingAsync does not support CancellationTokenSource so how can I cancel the last ping to perform a new one to prevent a lot of pings?

When the server is lost it takes seconds to PingServer() return a false value.

This is how I call PingServer():

var task = await PingServer();

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

Why I use ping? because when I want to get a table from SQL server if the server is disconnected my app enter a breakpoint.

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;
    }
}

EDIT : I used ping to reduce chance of entering my app in brake mode by getting a table from database. is there any other way to prevent break mode ? is it best way to ping server before calling dc.GetTable() ?

Break point

Upvotes: 1

Views: 1843

Answers (3)

ironstone13
ironstone13

Reputation: 3453

The system you depend on might fail, or the connection can go down right after your ping, when you're executing your code.

This is why a retry strategy is a much more robust approach then simply pinging a system before calling it.

Here is how you can implement a retry Cleanest way to write retry logic?

I would go with a retry approach, but if you still want to stay with your design you could

  • Schedule a periodic task to ping the system in question Is there a Task based replacement for System.Threading.Timer?
  • Make sure you schedule this periodic task in one central place (application startup or the like)
  • Invoke your PingServer from this periodic task and make sure you call Ping.SendAsync with PingOptions.Timeout being set, see this overload
  • From your PingServer set some kind of shared state, it could be a static variable, or an implementation of the Registry pattern
  • Make sure your shared state is thread-safe
  • The rest of your code can call this shared state, to find out if a system is online and available

As you can see, this approach is more complex, but you will prevent "lots of pings" to the system you depend on

Upvotes: 1

Nkosi
Nkosi

Reputation: 247551

Consider

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;
        }
    }
}

Where the ping is done with a cancellation token using Task.Run; If the ping result returns before the allotted time then all is well.

wrapped the component in a using to dispose of it when exiting function.

Upvotes: 2

jmdon
jmdon

Reputation: 1017

Have you considered using the timeout parameter?

From the documentation:

This overload allows you to specify a time-out value for the operation.

If that doesn't suffice and your problem is that the ping call is blocking, you could perform it on a background thread providing this is tightly controlled.

Upvotes: 3

Related Questions