Страницы

Поиск по вопросам

пятница, 20 марта 2020 г.

Task завершается через 15 минут работы

#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.

Комментариев нет:

Отправить комментарий