На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> System.Threading.Timer каждый раз создает поток?
    Хочу использовать поточный таймер. Сделал класс

    ExpandedWrap disabled
      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 минуты, то думаю пул потоков подойдет. ThreadPool.AddQueueWorkItem
      Могу ошибаться, но он не удаляет потоки после завершения операции, а использует из для выполнения следующего кода в очереди.

      А на кпк это так критично?
        Цитата GarF1eld @
        А на кпк это так критично?

        Да я не знаю... Это первое что я делаю для кпк.
        Вообще не аккуратно как-то. Зачем пересоздавать потоки на каждую итерацию, если можно в одном просто с определенной периодичностью выполнять нужный код.
          Сначала не обратил особого внимания на идентификаторы потоков. Видно, что все операции выполняются в 2х потоках: 0x77247002 и 0xd6b036ae. Сам же таймер "за кулисами" вызывает все тот же ThreadPool.QueueUserWorkItem. Скорее всего, когда вызывается коллбэк, один поток все еще занят, поэтому из пула потоков извлекается другой и в нем выполняется код. Когда приходит время следующего коллбека, первый уже отработал и помещен обратно в пул.

          То есть на самом деле потока только 2, а не по одному на каждый коолбек, что вообщем-то и показывает нам Output
            Точно, я то же че-то не обратил внимание, что два...
            Вообще странно, если учесть, что в колбэке только инкремент поля, а период вызова 1 секунда... Неуже инкремент требует больше вермени чем секунда?

            Вообще наколько корректно в .Net и в CF в частности так создавать потоки? Какжется мне, что накладные расходы на это больше чем в одном потоке эти счетчики инкрементировать.
            ПРосто планируется множество таймеров... хотя, какое множество, штук 20 всего... ну может 50. Что бы не делать таймер из WinForm, те. не завязываться на сообщения и не иметь соответственно большую погрешнать да еще и плавающую в зависимости от нагрузки решил сделать каждый таймер в своем потоке... вот теперь уже не уверен в том, что это правильное решение.
              Цитата Felan @
              Неуже инкремент требует больше вермени чем секунда?

              CLR сама решает какой поток из пула использовать. А как она это делает точно не скажу.
              Если много операций стоит в очереди, создается дополнительный поток для выполнения, после выполнения поток становится в пул на 2 минуты, и если его в течении этого времени пул не дернет, то он будет уничтожен.

              Вполне вероятно, что для коллбэки всех таймеров будут выполняться в 2х - 3ти потоках.

              Цитата Felan @
              Вообще наколько корректно в .Net и в CF в частности так создавать потоки?

              По-моему вполне корректно. Если это идет в разрез с чем-то, то можно использовать SynchronizationContext. Тогда можно будет создать один фоновый поток и выполнять в нем операции, вызывая методы Post или Send ..

              Добавлено
              но опять-же поток нужно будет как-то поддерживать на плаву - чтобы не отработал и умер :)
                Ясно. Спасибо за разяснения.
                +
                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                0 пользователей:


                Рейтинг@Mail.ru
                [ Script execution time: 0,0253 ]   [ 15 queries used ]   [ Generated: 8.07.25, 16:42 GMT ]