Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
0 / 0 / 0
Регистрация: 29.04.2016
Сообщений: 9

Timer.Elapsed vs Thread.sleep vs Что-то еще? И управление потоками

11.04.2019, 14:59. Показов 2662. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток! Прошу помощи уважаемого сообщества.
Суть: пишу относительно небольшое приложение для получения информации с контроллера Siemens S400.
Приложение должно с определенным интервалом времени "снимать" показания с разных датчиков.
Для связи с контроллером использую библиотеку S7.Net, и тут главная загвоздка - библиотека не умеет использовать нескольких одновременных подключений. а значит опрос нужно проводить последовательно.
Для понимания логики работы кратко опишу алгоритм одного из элементов:
1) С интервалом 1сек считываем показания с датчика наличия (D1), на входе в зону.
2) Как только получили true, останавливаем опрос текущего датчика, и начинаем считывать с периодом показания с двух других (D2 - датчик наличия на выходе, период опроса 1сек, D3 - текущее давление, период опроса 100мс).
3) Пока D2 не вернет true, значения с D3 собираем в массив, затем математика.
4) Запускаем весь цикл по новой.

Изначально попробовал сделать на System.Timers.timer'ах:

Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
static object loker = new object();
static list<double> array = new list<double>();
 
Static void Main(string args)
{
timer_Entry.Start(); // в timer_Entry.Elapsed вызывается read_Entry()
}
 
public void read_Entry()
{
lock (locker)
{
bool result = (bool)(plc.read("I1.1")); // здесь получаем значение на вход
if (result)
{
array.clear();
timer_Entry.Stop();
timer_Exit.Start(); // в timer_Exit.Elapsed вызывается read_Exit()
timer_Read.Start(); // в timer_Read.Elapsed вызывается read_Data()
}
}
}
 
read_Exit()
{
lock (locker)
{
bool result = (bool)(plc.read("I1.2")); // здесь получаем значение на выход
if (result )
{
timer_Exit.Stop();
timer_Read.Stop();
timer_Entry.Start();
pareseArray();
}
}
}
 
read_Data()
{
lock (locker)
{
array.add(Convert.ToDouble(plc.Read(DataType.DataBlock, 1, 1, VarType.Real, 1))); //здесь получаем текущее давление и пишем в массив
}
}


И вроде все работает, за исключение Большого НО : из за Timer.AutoReset = true создается куча потоков, которые не получается убить Timer.stop(); Timer.Dispose(); как я тут только не пробовал... OutOfMemoryExeption
В результате Timer.AutoReset поставил в false, и вызывал Timer.Start(). Плодов не принесло.

Как правильно организовать подобную задачу на таймерах? Или создавать новые потоки каждый раз, потом Thread.Sleep(), а затем убивать их? Кстаи, Thread.CurrentThread.Abort() у меня почему-то тоже не получилось. Или использовать другое решение? Есть добрые люди которые смогут подсказать?
ЗыСы: многопоточность для меня очень новое понятие.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
11.04.2019, 14:59
Ответы с готовыми решениями:

Thread.Sleep() или Timer. Что лучше использовать?
Здраствуйте уважаемые знатоки. Мне нужно опрашивать определенный метод с переодичностью 30 сек. Что лучше использовать чтобы нагрузка...

Timer and elapsed time
Можно ли у запущенного таймера определить время, через которое он отработает ? То есть сколько ему осталось до запуска TimerTask.

Работа с повторяющимся событием (Timer.Elapsed)
Всем доброго времени суток! В общем-то столкнулся со следующей проблемой: Необходимо задать повторяющееся событие (метод). Я так понял...

3
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
12.04.2019, 00:29
Лучший ответ Сообщение было отмечено M03Gen как решение

Решение

Цитата Сообщение от M03Gen Посмотреть сообщение
из за Timer.AutoReset = true создается куча потоков
Во-первых, с чего вы взяли что Timer генерирует множество потоков? Это не так. Событие может генерироваться в разных потоках. Но это потоки из ThreadPool, и они не создаются специально для Timer.
Поэтому ваш OutOfMemoryExeption скорее всего не из-за потоков. Ищите причину в чем-то другом. В данном случае первым делом посмотрите профилировщик, из которого сразу будет видно откуда берется перерасход памяти.

Во-вторых, создавать кучу таймеров - не самая лучшая идея. Это усложняет логику, и создает побочные эффекты, которые трудно контролировать. Лучше создайте один таймер с большой частотой обновления. Внутри обработчика проверяйте условия и выполняйте действия. Если нужно например выполнить какое-то действие через 1 секунду, создайте в вашем классе поле
C#
1
DateTime TimeToRead = DateTime.Maximum;
Если вам нужно что-то прочитать через 1 секунду, присвойте в это поле что-то типа
C#
1
TimeToRead = DateTime.Now.addSeconds(1);
А в обработчике таймера проверяйте, наступил ли нужный момент времени:
C#
1
2
3
4
5
6
7
if(DateTime.Now > TimeToRead)
{
   //какие-то действия
   //...
   //сбрасываем время срабатывания
   TimeToRead = DateTime.Maximum;
}
Тогда все действия с устройством у вас будет в одном методе, синхронизация не понадобится, а алгоритм станет линейным.
1
0 / 0 / 0
Регистрация: 29.04.2016
Сообщений: 9
12.04.2019, 07:51  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Во-первых, с чего вы взяли что Timer генерирует множество потоков?
Эмм, уже не помню где, но несколько раз встречал в процессе гугления. Хотя и подозреваю что мог не так понять. Окончательный вывод сделал из этого: https://stackoverflow.com/ques... yexception

Предложенный Вами метод не плох. в какой-то мере я его и использовал в своем решении. Но что делать если необходимых сигналов не 3, а 1500? Описанная мной выше задача - всего лишь очень упрощенный пример, просто добавим к тем 4 действиям еще штук 5 для обработки новой логики. Причем новые действия должны происходить "параллельно" предыдущим 4.
В принципе, реализовать это так как Вы подсказали можно, но прогр алгоритм полагаю превратится в сплошное месиво из условий. Может можно реализовать Nое количество таймеров под каждую логическую последовательность и задействовать их параллельно друг с другом? Но тогда как их работу между собой синхронизировать?

Или может быть есть и другие варианты реализации подобной задачи?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
12.04.2019, 09:03
Цитата Сообщение от M03Gen Посмотреть сообщение
Эмм, уже не помню где, но несколько раз встречал в процессе гугления. Хотя и подозреваю что мог не так понять. Окончательный вывод сделал из этого: http://https://stackoverflow.c... yexception
Понятно. Это случается тогда, когда время работы обработчика тика дольше, чем период работы таймера. Что бы этого избежать, нужно останавливать работу таймера, пока идет обработка, а затем снова запускать его:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        var timer = new System.Timers.Timer(100);
        timer.AutoReset = true;
        timer.Elapsed += Timer_Elapsed;
        timer.Start();
 
        ....
 
        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            (sender as System.Timers.Timer).Stop();
            try
            {
                //processing
                //....
            }
            finally
            {
                (sender as System.Timers.Timer).Start();
            }
        }
Цитата Сообщение от M03Gen Посмотреть сообщение
Предложенный Вами метод не плох. в какой-то мере я его и использовал в своем решении. Но что делать если необходимых сигналов не 3, а 1500?
Во-первых, у алгоритма всегда есть минимальная сложность, меньше которой сделать нельзя. Если требуется 1500 проверок, значит так оно и есть, и никакие таймеры вам не помогут, все равно придется эти проверки сделать.
Другое дело - как это сделать, чисто технически.
В любом случае, непонятно как вам помогут 100500 таймеров. Вот где начнется каша...

Цитата Сообщение от M03Gen Посмотреть сообщение
Причем новые действия должны происходить "параллельно" предыдущим 4.
Но в вашем примере на самом деле нет параллельного выполнения, у вас везде стоит lock, а значит одновременно выполняется только один из обработчиков.

Цитата Сообщение от M03Gen Посмотреть сообщение
В принципе, реализовать это так как Вы подсказали можно, но прогр алгоритм полагаю превратится в сплошное месиво из условий. Может можно реализовать Nое количество таймеров под каждую логическую последовательность и задействовать их параллельно друг с другом? Но тогда как их работу между собой синхронизировать?
Или может быть есть и другие варианты реализации подобной задачи?
Если у вас множество каких-то процессов - ну так облегчите себе жизнь, не делайте тупо проверки типа if(DateTime.Now > TimeToRead), а сделайте упорядоченную очередь задач. Каждая задача будет иметь свое время срабатывания, а таймер будет периодически брать из очереди задачу, проверять наступило ли ее время и исполнять, если нужно. На самом деле можно придумать множество реализаций, тут проблемы нет.

Если не сможете реализовать самостоятельно, приведите более подробно условие задачи (приведите хотя бы два примере работы и опишите логику, подробно!!), могу написать простой пример реализации очереди.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.04.2019, 09:03
Помогаю со студенческими работами здесь

Timer - сколько времени осталось до Elapsed
Как можно получить время, которое осталось до истечения таймера?

Отсутствует событие Elapsed компонента Timer
Прошу подсказать в таком вопросе. Пишу примеры из книги Лабор &quot;Си Шарп Создание приложений для Windows&quot; И там в разделе 31. Таймер...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru