I have some code that I would like to use for device discovery on a network. It simply pings any ip address on said network and if it gets an answer, adds the address in a list.
Code looks like this:
static void Main(string[] args){
//do stuff to get subnetmask and local address
//succession of for loop to increment ip address
{
PingAsync(ip_address);
}
//here I display the list of addresses that answered the ping
//first Readline() is to manually wait for threads to end so the list isn't empty
Console.Readline()
Console.WriteLine("List of all devices found :\n");
ipList.ForEach(delegate (string str)
{
Console.WriteLine($"\t=> {str}");
});
Console.ReadLine();
}
private static void PingAsync(IPAddress address)
{
AutoResetEvent waiter = new AutoResetEvent(false);
Ping pingSender = new Ping();
//items are added to ipList in PingCompletedCallback()
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 1200;
PingOptions options = new PingOptions(64, true);
pingSender.SendAsync(address, timeout, buffer, options, waiter);
}
In the PingCompletedCallback method, I add items to a list that will be displayed in the main
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
Program prog = new Program();
if (e.Cancelled)
{
Console.WriteLine("Ping failed !");
Console.WriteLine(e.Error.ToString());
((AutoResetEvent)e.UserState).Set();
}
if(e.Error != null)
{
Console.WriteLine("Ping failed !");
Console.WriteLine(e.Error.ToString());
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
if(reply.Status.ToString().Equals("Success", StringComparison.OrdinalIgnoreCase))
{
//If the ping succeeds add the address to a list
ipList.Add(reply.Address.ToString());
}
((AutoResetEvent)e.UserState).Set();
}
The code works fine at discovering devices, only issue is with the list of addresses. If I don't manually wait for all threads to end it will appear empty.
According these posts (1) (2) and some other, using Thread.join or Task.Waitall are the way to go. However, unlike them I am not creating threads myself but letting SendAsync() create its own thread.
Also, I can't change PingAsync() to make it await SendAsync() since it returns void.
I would like to know you would go about waiting for threads to end before printing/using the ipList.