#c_sharp
Написал программу которая должна раз в секунду проверять ping до двух серверов. Проблема в том, что примерно через 15 минут таски перестают выполняться. В выводе вижу такое: Ping: 87.250.250.242 Status: Success Time: 17.10.2019 15:18:51 Ping: 8.8.8.8 Status: Success Time: 17.10.2019 15:18:52 Ping: 87.250.250.242 Status: Success Time: 17.10.2019 15:18:52 Поток 0x65f0 завершился с кодом 0 (0x0). Поток 0x324 завершился с кодом 0 (0x0). Поток 0x46c4 завершился с кодом 0 (0x0). Поток 0x5fac завершился с кодом 0 (0x0). Поток 0x4b00 завершился с кодом 0 (0x0). Ну и естественно таски никакие исключения не кидают. Хотя вроде должны работать постоянно. static void Main(string[] args) { Run(); Console.ReadKey(); } private static void PingTimeout(string srv) { Console.WriteLine($"Warning! {srv} server timeout, {DateTime.Now}"); } private static async void Run() { Task allTasks = null; try { Task t1 = Task.Run(() => CheckConnection("8.8.8.8", 1000)); Task t2 = Task.Run(() => CheckConnection("87.250.250.242", 1000)); allTasks = Task.WhenAll(t1, t2); await allTasks; } catch(Exception ex) { Console.WriteLine($"Critical! {ex.Message}"); Console.WriteLine("IsFaulted: " + allTasks.IsFaulted); foreach (var inx in allTasks.Exception.InnerExceptions) { Console.WriteLine("Внутреннее исключение: " + inx.Message); } } } private static void CheckConnection(string srvAddress, int interval) { TimerCallback timerCallBack = new TimerCallback(PingServer); Timer timer = new Timer(timerCallBack, srvAddress, 0, interval); } private static void PingServer(object obj) { MyClass instance = new MyClass(); instance.myEvent += new EventDelegate(PingTimeout); string target = (string)obj; Ping ping = new Ping(); int timeout = 1280; string data = "sjfhksjfdkjsdjfkjsdfskjdhfksh"; byte[] buffer = Encoding.ASCII.GetBytes(data); PingOptions options = new PingOptions(128, true); PingReply pingReply; try { pingReply = ping.Send(target, timeout, buffer, options); Debug.WriteLine($"Ping: {pingReply.Address} Status: {pingReply.Status} Time: {DateTime.Now}"); switch (pingReply.Status) { case IPStatus.Success: //Debug.WriteLine($"success {pingReply.Address}"); break; case IPStatus.TimedOut: instance.InvokeEvent(target); break; default: //Debug.WriteLine($"unknown {pingReply.Address}"); break; } } catch(Exception ex) { Console.WriteLine($"Critical! exception {ex.Message} at {DateTime.Now}"); } ping.Dispose(); }
Ответы
Ответ 1
В вашем коде таски (которые Task) завершаются почти мгновенно, по возврату из CheckConnection. Через некоторое время вызовы PingServer создают достаточно много новых объектов, чтобы триггернулась сборка мусора. На таймеры у вас есть ссылки только из локальных переменных уже завершенного метода, ссылок из корней нет - и сборщик мусора убивает их как недостижимые. Это типовая ошибка, о ней даже в описании класса Timer упомянуто: As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.
Комментариев нет:
Отправить комментарий