
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.52] |
![]() |
|
Сообщ.
#1
,
|
|
|
Хочу использовать поточный таймер. Сделал класс
![]() ![]() using ThreadTimer = System.Threading.Timer; ... public class Timer { public readonly int TimerPeriodMs = 1000; public string Name { get; set; } public DateTime? StartDate { get; private set; } public DateTime CreateDate { get; private set; } public ushort PricePerHour { get; set; } public CurrencyTypes Currency { get; set; } public long Seconds { get; private set; } public TimeSpan Span { get { return TimeSpan.FromSeconds(Seconds); } } public bool Started { get; private set; } private readonly ThreadTimer _Tmr; public Timer(string name, ushort pricePerHour, CurrencyTypes currency) { Name = name; PricePerHour = pricePerHour; Currency = currency; StartDate = null; CreateDate = DateTime.Now; Seconds = 0; Started = false; _Tmr = new ThreadTimer( DoOnTimer, null , Timeout.Infinite, TimerPeriodMs ); } public Timer(string name, ushort pricePerHour, CurrencyTypes currency, DateTime startDate, long seconds) : this(name, pricePerHour, currency) { StartDate = startDate; Seconds = seconds; } public void Start() { _Tmr.Change(0, TimerPeriodMs); Started = true; } public void Stop() { _Tmr.Change(Timeout.Infinite, TimerPeriodMs); Started = false; } private void DoOnTimer(Object obj) { Seconds++; } } Создаю его, вызываю метот Start. Таймер запускается и все работает как надо, но в окне Output во время работы программы появляются соощения вида: Цитата The thread 0x77247002 has exited with code 0 (0x0). The thread 0xd6b036ae has exited with code 0 (0x0). The thread 0x77247002 has exited with code 0 (0x0). The thread 0xd6b036ae has exited with code 0 (0x0). The thread 0x77247002 has exited with code 0 (0x0). The thread 0xd6b036ae has exited with code 0 (0x0). The thread 0x77247002 has exited with code 0 (0x0). The thread 0xd6b036ae has exited with code 0 (0x0). Как я понимаю это говорит о том, что каждую секунду создается новый поток, в нем выполняется кэлбэк. Это так? Я рассчитывал, что поток будет создан один, и из него будет переодически вызываться кэлбэк. Что тогда можно использовать, что бы не создавать постоянно потоки? Ну за исключением конечно полностью ручного создания потока. |
Сообщ.
#2
,
|
|
|
Если таймер уснановлен меньше чем в 2 минуты, то думаю пул потоков подойдет. ThreadPool.AddQueueWorkItem
Могу ошибаться, но он не удаляет потоки после завершения операции, а использует из для выполнения следующего кода в очереди. А на кпк это так критично? |
Сообщ.
#3
,
|
|
|
Цитата GarF1eld @ А на кпк это так критично? Да я не знаю... Это первое что я делаю для кпк. Вообще не аккуратно как-то. Зачем пересоздавать потоки на каждую итерацию, если можно в одном просто с определенной периодичностью выполнять нужный код. |
Сообщ.
#4
,
|
|
|
Сначала не обратил особого внимания на идентификаторы потоков. Видно, что все операции выполняются в 2х потоках: 0x77247002 и 0xd6b036ae. Сам же таймер "за кулисами" вызывает все тот же ThreadPool.QueueUserWorkItem. Скорее всего, когда вызывается коллбэк, один поток все еще занят, поэтому из пула потоков извлекается другой и в нем выполняется код. Когда приходит время следующего коллбека, первый уже отработал и помещен обратно в пул.
То есть на самом деле потока только 2, а не по одному на каждый коолбек, что вообщем-то и показывает нам Output |
Сообщ.
#5
,
|
|
|
Точно, я то же че-то не обратил внимание, что два...
Вообще странно, если учесть, что в колбэке только инкремент поля, а период вызова 1 секунда... Неуже инкремент требует больше вермени чем секунда? Вообще наколько корректно в .Net и в CF в частности так создавать потоки? Какжется мне, что накладные расходы на это больше чем в одном потоке эти счетчики инкрементировать. ПРосто планируется множество таймеров... хотя, какое множество, штук 20 всего... ну может 50. Что бы не делать таймер из WinForm, те. не завязываться на сообщения и не иметь соответственно большую погрешнать да еще и плавающую в зависимости от нагрузки решил сделать каждый таймер в своем потоке... вот теперь уже не уверен в том, что это правильное решение. |
Сообщ.
#6
,
|
|
|
Цитата Felan @ Неуже инкремент требует больше вермени чем секунда? CLR сама решает какой поток из пула использовать. А как она это делает точно не скажу. Если много операций стоит в очереди, создается дополнительный поток для выполнения, после выполнения поток становится в пул на 2 минуты, и если его в течении этого времени пул не дернет, то он будет уничтожен. Вполне вероятно, что для коллбэки всех таймеров будут выполняться в 2х - 3ти потоках. Цитата Felan @ Вообще наколько корректно в .Net и в CF в частности так создавать потоки? По-моему вполне корректно. Если это идет в разрез с чем-то, то можно использовать SynchronizationContext. Тогда можно будет создать один фоновый поток и выполнять в нем операции, вызывая методы Post или Send .. Добавлено но опять-же поток нужно будет как-то поддерживать на плаву - чтобы не отработал и умер ![]() |
Сообщ.
#7
,
|
|
|
Ясно. Спасибо за разяснения.
+ |