Ping.SendAsync не выполняет обратный вызов PingCompletedEventHandler
-
20-12-2019 - |
Вопрос
У меня возникли некоторые проблемы с методом SendAsync при передаче недопустимого IP-адреса - 0.0.0.51
Проблема в том, что метод обратного вызова (pingSender_PingCompleted) даже не вызывается.Я не вижу никаких ошибок, каких бы то ни было.
IP-адрес.TypeParse находит этот IP-адрес как "действительный" IP.
Вот мой код;пожалуйста, дайте мне знать, чего я здесь не вижу.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Program c = new Program();
try
{
c.PingStore("0.0.0.51");
Console.WriteLine("Pinged without exceptions");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void PingStore(string ipAddress)
{
Ping pingSender = new Ping();
pingSender.PingCompleted += new PingCompletedEventHandler(pingSender_PingCompleted);
pingSender.SendAsync(ipAddress, null);
}
private void pingSender_PingCompleted(object sender, PingCompletedEventArgs e)
{
Console.WriteLine("PingCompleted invoked. continue to be happy");
}
}
}
Пожалуйста, обратите внимание, что я не могу:
Иметь какой-либо контроль над тем, что поступает через IPAddress
Усложните мой код, используя регулярное выражение
Решение
Я протестировал ваши два метода в простом консольном приложении, и я получаю PingException
для 0.0.0.51
точно так же , как itsme86 прокомментировал.
Это мое предположение о том, что происходит:ваш комментарий "Я ожидаю, что этот метод будет вызываться 100 раз одновременно". плюс pingSender_PingCompleted
отсутствие вызова подразумевает, что вы вызываете PingStore
метод в рабочем потоке (например,используя ThreadPool
).Это было бы причиной, по которой вы не можете поймать PingException
в вашем основном потоке, пока pingSender_PingCompleted
никогда не вызывается из-за исключения.
Обновить
В своем комментарии вы написали "К вашему сведению, я работаю на .Net 4.0"..
Вы на 100% уверены, что ваше приложение нацелено на версию 4.0, а не на версию 5 или более раннюю?
Я смог воспроизвести вашу проблему, используя ваш точный код, но при таргетинге на .NET Framework версии v3.5 (для версии 4.0 генерируется исключение с использованием вашего кода).
Я немного покопался в System.dll для обеих версий фреймворка, и вот что я нашел:
- Обе версии фреймворка внутри
Ping
класс в методеprivate PingReply InternalSend(...)
используйте собственный методnum = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2
. - В случае ошибки
num
установлено значение0
, и я обнаружил, что каждая версия Фреймворка обрабатывает эту ситуацию по-разному.
Фреймворк v3.5/2.0:
if (num == 0)
{
num = Marshal.GetLastWin32Error();
if (num != 0)
{
this.FreeUnmanagedStructures();
return new PingReply((IPStatus)num);
}
}
Framewrk v4.0/4.5:
if (num == 0)
{
num = Marshal.GetLastWin32Error();
if (async && (long)num == 997L)
{
return null;
}
this.FreeUnmanagedStructures();
this.UnregisterWaitHandle();
if (async || num < 11002 || num > 11045)
{
/* NOTE! This throws the exception for 0.0.0.51 address that you're not getting */
throw new Win32Exception(num);
}
return new PingReply((IPStatus)num);
}
Как вы можете видеть из приведенных выше фрагментов кода, в .NET версии 4.0 вы должны быть в состоянии перехватить исключение, в то время как в .NET версии 5 все собственные ошибки WIN32 обрабатываются автоматически.