2012-02-07 3 views
0

Я никогда не работаю слишком много с таймерами и задержками, поэтому я уверен, что делаю что-то действительно уродливое с моим кодом, но я не могу найти решение.Время ожидания внутреннего метода

Хорошо ... У меня есть класс под названием AnimatorsPool, который содержит и обрабатывает много классов Animator одновременно. Аниматор - просто простой, управляемый таймером управляющий.

public sealed class AnimatorsPool : IDisposable 
    { 
     private Boolean m_Disposed; 
     private Boolean m_Stopped; 
     private Boolean m_Waiting; 
     private Int32 m_DelayBetween; 
     private Int32 m_DelayStart; 
     private List<Animator> m_Animators; 
     private Stopwatch m_Stopwatch; 

     public Boolean AnimationsFinished 
     { 
      get 
      { 
       foreach (Animator animator in m_Animators) 
       { 
        if (!animator.AnimationFinished) 
         return false; 
       } 

       return true; 
      } 
     } 

     public AnimatorsPool(Int32 delayBetween, Int32 delayStart) 
     { 
      m_Disposed = false; 
      m_Stopped = false; 
      m_Waiting = false; 
      m_DelayBetween = ((delayBetween < 0) ? 0 : delayBetween); 
      m_DelayStart = ((delayStart < 0) ? 0 : delayStart); 
      m_Animators = new List<Animator>(); 
     } 

     private void Wait(Int32 delay) 
     { 
      m_Stopwatch = Stopwatch.StartNew(); 

      m_Waiting = true; 

      while (!m_Stopped && (m_Stopwatch.ElapsedMilliseconds <= delay)) 
       Application.DoEvents(); 

      m_Waiting = false; 

      m_Stopwatch.Stop(); 
     } 

     public void Add(Animator animator) 
     { 
      m_Animators.Add(animator); 
     } 

     public void Dispose() 
     { 
      if (!m_Disposed) 
      { 
       foreach (Animator animator in m_Animators) 
        animator.Dispose(); 

       m_Animators.Clear(); 
       m_Animators = null; 

       m_Disposed = true; 
      } 

      GC.SuppressFinalize(this); 
     } 

     public void Start() 
     { 
      if (m_Animators.Count > 0) 
      { 
       if (m_DelayStart > 0) 
        Wait(m_DelayStart); 

       m_Animators[0].Start(); 

       if (m_Animators.Count > 1) 
       { 
        for (Int32 i = 1, length = m_Animators.Count; i < length; ++i) 
        { 
         if (m_DelayBetween > 0) 
          Wait(m_DelayBetween); 

         m_Animators[i].Start(); 
        } 
       } 
      } 
     } 

     public void Stop() 
     { 
      m_Stopped = true; 

      while (m_Waiting) 
       Application.DoEvents(); 
     } 
    } 

Внутри моей основной форме, иногда с использованием AnimatorsPool, я использую следующий код:

 using (AnimatorsPool pool = new AnimatorsPool(100, (delayAction ? 100 : 0))) 
     { 
      m_AnimatorsPools.Add(pool); 

      for (Int32 i = (controlsCount - 1); i >= 0; --i) 
      { 
       Animator animator = new Animator(controls[i], coordinates[i], 50); 
       pool.Add(animator); 
      } 

      pool.Start(); 

      while (!pool.AnimationsFinished) 
       Application.DoEvents(); 

      m_AnimatorsPools.Remove(pool); 
     } 

Хорошо, теперь ... что случилось в начале было то, что, если я вышел из программы во время AnimatorsPool все еще запускал метод Wait(), моя основная форма исчезала, но из-за этого процесс все еще выполнялся неопределенно в моем диспетчере задач. Поэтому я реализовал Dispose переопределение в моей основной форме:

protected override void Dispose(Boolean disposing) 
    { 
     if (!m_Disposed) 
     { 
      if (disposing) 
      { 
       s_RandomProvider.Dispose(); 

       foreach (AnimatorsPool pool in m_AnimatorsPools) 
        pool.Dispose(); 

       m_AnimatorsPools.Clear(); 
       m_AnimatorsPools = null; 
      } 

      m_Disposed = true; 
     } 

     base.Dispose(disposing); 
    } 

Ok ... теперь моя программа выходит правильно иногда, но иногда нет. И что я вижу из отладки, так это то, что когда это происходит, это связано с тем, что некоторые AnimatorsPool все еще используют метод Wait(), даже если для m_Stopped установлено значение true. Думаю, я должен использовать потоки, таймеры или что-то в этом роде, но у меня нет опыта. Любая помощь приветствуется! Благодаря!

ответ

0

Что бы вы ни делали, не делает этого:

while (!m_Stopped && (m_Stopwatch.ElapsedMilliseconds <= delay)) 
    Application.DoEvents(); 

Вы должны использовать таймеры и событийные для этого, а не занятого-ожидания. Это только когда-либо хорошо во встроенных в реальном времени материалах.

Вам нужно переписать свой код в значительной степени, и трудно дать вам указатели, не создавая урок по таймерам и развитию событий.

EDIT: Из Application.DoEvents документации MSDN (курсив мой):

Вызов этого метода приводит к тому, текущий поток приостанавливается, пока все ждут окна сообщения обрабатываются. Если сообщение вызывает срабатывание события, тогда могут выполняться другие другие области вашего кода приложения. Это может привести к тому, что ваше приложение проявит неожиданное поведение, которое трудно отлаживать. Если вы выполняете операции или вычисления, которые занимают много времени, часто желательно, чтобы выполнял эти операции над новым потоком. Для получения дополнительной информации об асинхронном программировании см. Asynchronous Programming Overview.

+0

Должен ли я разделить мой метод Start, чтобы использовать два таймера с событием Tick? –

+0

Это очень хорошая отправная точка. –

+0

Отредактировано для добавления дополнительной информации. –

Смежные вопросы