I'm working on this program to ping a large number of IP Address simultaneously I tried simply pinging each address one at a time but Once I started pinging 50+ hosts it got insanely long. The problem I'm having is that I am unable to stop the asynchronous thread on the cancel button click and get this error when I try and ping more than 1 host. I've spent 2 days trying to get it figured out and had no luck. The exact error is as follows:
System.InvalidOperationException: An asynchronous call is already in progress. It must be completed or canceled before you can call this method. at System.Net.NetworkInformation.Ping.CheckStart(Boolean async) at System.Net.NetworkInformation.Ping.Send(IPAddress address, Int32 timeout, Byte[] buffer, PingOptions options) at MultiPing.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in f:\Dev\tfsMultiPing\Multi Ping\MultiPing\MultiPing\Form1.cs:line 139
private void pingBtn_Click(object sender, EventArgs e)
{
try
{
if (inputBox.Text == "")
{
MessageBox.Show("Please Enter an IP Address to Ping.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
if (backgroundWorker1.IsBusy != true)
{
backgroundWorker1.RunWorkerAsync();
}
else
{
MessageBox.Show("Please Cancel current Ping or wait for it to be completed");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
try
{
this.Invoke(new MethodInvoker(delegate { progressBar1.Enabled = true; }));
int i;
//Add each line in the input box to the "allLines" string array
string[] allLines = inputBox.Lines;
Ping pingSender = new Ping();
try
{
//Get an object that will block the main thread
AutoResetEvent waiter = new AutoResetEvent(false);
//When the PingCompleted even is raised,
//The PingCompletedCallback method is called.
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
//Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
//Wait 2 seconds for a reply.
int timeout = 2000;
//Set Options for transmission:
//The data can go through 64 gateways or routers
//before it is destroyed, and the data packet
//cannot be fragmented
PingOptions options = new PingOptions(64, true);
//Check if Cancel Button was clicked
if (backgroundWorker1.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
//Begin Loop to ping each given IP Address
for (i = 0; i < allLines.Length; i++)
{
//Check if Cancel Button was clicked
if (backgroundWorker1.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
//Convert each line from the input box to an IP address
IPAddress address = IPAddress.Parse(allLines[i]);
//Send ping Asynchronously
//Use the waiter as the user token.
//When the callback complets, it can wake up this thread.
pingSender.SendAsync(address, timeout, buffer, options, waiter);
PingReply reply = pingSender.Send(address, timeout, buffer, options);
waiter.WaitOne();
//If a replay is recieved Print "IP Address" is up in the output box.
if (reply.Status == IPStatus.Success)
{
this.Invoke(new MethodInvoker(delegate { outputBoxLive.AppendText(address + " is up" + Environment.NewLine); }));
}
//If no reply is recieved then print "IP Address" is down in the output box.
else if (reply.Status == IPStatus.TimedOut)
{
this.Invoke(new MethodInvoker(delegate { outputBoxDown.AppendText(address + " is down" + Environment.NewLine); }));
pingSender.Dispose();
}
pingSender.Dispose();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void pingStuff()
{
}
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
//If the operation was cancelled, Display a message to the user
if (e.Cancelled)
{
MessageBox.Show("Ping Cancelled");
//Let the main thread resume.
//User token is the AutoResetEvent object that the main thread is waiting for
((AutoResetEvent)e.UserState).Set();
}
//If an error occurred, Display the exception to the user.
if (e.Error != null)
{
MessageBox.Show("Ping Failed: " + e.Error.ToString());
//Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
DisplayReply(reply);
//Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
public static void DisplayReply(PingReply reply)
{
if (reply == null)
return;
Console.WriteLine("ping status: [0]", reply.Status);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
}
}
public void button2_Click(object sender, EventArgs e)
{
try
{
backgroundWorker1.CancelAsync();
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
}
}
}
Invokeyou need to callEndInvokefrom the callback, this ends the call. - MgetzBeginInvoke(), notInvoke(). It doesn't apply here. And note that while conventionally it's true that one should match pairs ofBeginXXX()andEndXXX()methods, in the case ofControl.BeginInvoke()and the compiler-generated delegate types'BeginInvoke()methods, Microsoft has for years offered the guidance that one need not callEndInvoke()in those cases (i.e. they are an exception to the rule). - Peter Duniho