Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. Timer inifinite loop

Timer inifinite loop

Scheduled Pinned Locked Moved Clever Code
sysadmin
10 Posts 4 Posters 4 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Ami Bar
    wrote on last edited by
    #1

    Look at the code below, from first observation it looks fine. However, it gets into an infinite loop. This code synchronizes a file changes between two machines (A and B). Every time there is a change in the file on A the whole file has to be passed to machine B. (The file doesn't change on machine B). In order to avoid the network traffic on every change, there is a mechanism that passes the file only if didn't it change for the past last minute. The Scheduler is an external class that is used as a timer. When Scheduler::Schedule is called the scheduled method will be called every interval until the Scheduler::Unschedule is called. All the methods of MyClass (including the constructor) executes on the same thread!!!

    // Header
    class MyClass
    {
    public:
    MyClass();
    void FileChanged();
    void PassFile();

    private:
    long m_nTimerID;
    Scheduler m_pScheduler;
    };

    // Class
    MyClass::MyClass()
    {
    m_nTimerID = 0;
    m_pScheduler = new Scheduler();
    }

    void MyClass::FileChanged()
    {
    if (0 != m_nTimerID)
    {
    // Unschedule the old timer
    m_pScheduler->Unschedule(m_nTimerID);
    }

    // This line will call to MyClass::PassFile every 60 seconds from now
    m\_nTimerID = m\_pScheduler->Schedule(60\*1000, &PassFile);
    

    }

    MyClass::PassFile()
    {
    if (0 != m_nTimerID)
    {
    // Unschedule the old timer
    m_pScheduler->Unschedule(m_nTimerID);
    m_nTimerID = 0;
    }

    // Pass the file...
    

    }

    Try to find out what's causing the infinite loop. I'll post the answer later. Hint: I used the ACE::HeapTimer (I don't remember the exact class name) to implement the Scheduler class. Ami

    G E A 3 Replies Last reply
    0
    • A Ami Bar

      Look at the code below, from first observation it looks fine. However, it gets into an infinite loop. This code synchronizes a file changes between two machines (A and B). Every time there is a change in the file on A the whole file has to be passed to machine B. (The file doesn't change on machine B). In order to avoid the network traffic on every change, there is a mechanism that passes the file only if didn't it change for the past last minute. The Scheduler is an external class that is used as a timer. When Scheduler::Schedule is called the scheduled method will be called every interval until the Scheduler::Unschedule is called. All the methods of MyClass (including the constructor) executes on the same thread!!!

      // Header
      class MyClass
      {
      public:
      MyClass();
      void FileChanged();
      void PassFile();

      private:
      long m_nTimerID;
      Scheduler m_pScheduler;
      };

      // Class
      MyClass::MyClass()
      {
      m_nTimerID = 0;
      m_pScheduler = new Scheduler();
      }

      void MyClass::FileChanged()
      {
      if (0 != m_nTimerID)
      {
      // Unschedule the old timer
      m_pScheduler->Unschedule(m_nTimerID);
      }

      // This line will call to MyClass::PassFile every 60 seconds from now
      m\_nTimerID = m\_pScheduler->Schedule(60\*1000, &PassFile);
      

      }

      MyClass::PassFile()
      {
      if (0 != m_nTimerID)
      {
      // Unschedule the old timer
      m_pScheduler->Unschedule(m_nTimerID);
      m_nTimerID = 0;
      }

      // Pass the file...
      

      }

      Try to find out what's causing the infinite loop. I'll post the answer later. Hint: I used the ACE::HeapTimer (I don't remember the exact class name) to implement the Scheduler class. Ami

      G Offline
      G Offline
      Galatei
      wrote on last edited by
      #2

      Hi, Could you post Schedule(...) function code? If PassFile is callback function, initialized to be called from SetTimer() function, then it should be declared as static, and its proper definition look like this: ((CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) Anyway, the m_nTimerID variable has to be passed by pointer, since use of non-static variables in static functions, is not supposed to happen. Regards

      A 1 Reply Last reply
      0
      • G Galatei

        Hi, Could you post Schedule(...) function code? If PassFile is callback function, initialized to be called from SetTimer() function, then it should be declared as static, and its proper definition look like this: ((CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) Anyway, the m_nTimerID variable has to be passed by pointer, since use of non-static variables in static functions, is not supposed to happen. Regards

        A Offline
        A Offline
        Ami Bar
        wrote on last edited by
        #3

        The Schedule is not implemented with the SetTimer. It has nothing to do with Windows. The callback call has no problem. Ami

        1 Reply Last reply
        0
        • A Ami Bar

          Look at the code below, from first observation it looks fine. However, it gets into an infinite loop. This code synchronizes a file changes between two machines (A and B). Every time there is a change in the file on A the whole file has to be passed to machine B. (The file doesn't change on machine B). In order to avoid the network traffic on every change, there is a mechanism that passes the file only if didn't it change for the past last minute. The Scheduler is an external class that is used as a timer. When Scheduler::Schedule is called the scheduled method will be called every interval until the Scheduler::Unschedule is called. All the methods of MyClass (including the constructor) executes on the same thread!!!

          // Header
          class MyClass
          {
          public:
          MyClass();
          void FileChanged();
          void PassFile();

          private:
          long m_nTimerID;
          Scheduler m_pScheduler;
          };

          // Class
          MyClass::MyClass()
          {
          m_nTimerID = 0;
          m_pScheduler = new Scheduler();
          }

          void MyClass::FileChanged()
          {
          if (0 != m_nTimerID)
          {
          // Unschedule the old timer
          m_pScheduler->Unschedule(m_nTimerID);
          }

          // This line will call to MyClass::PassFile every 60 seconds from now
          m\_nTimerID = m\_pScheduler->Schedule(60\*1000, &PassFile);
          

          }

          MyClass::PassFile()
          {
          if (0 != m_nTimerID)
          {
          // Unschedule the old timer
          m_pScheduler->Unschedule(m_nTimerID);
          m_nTimerID = 0;
          }

          // Pass the file...
          

          }

          Try to find out what's causing the infinite loop. I'll post the answer later. Hint: I used the ACE::HeapTimer (I don't remember the exact class name) to implement the Scheduler class. Ami

          E Offline
          E Offline
          Ennis Ray Lynch Jr
          wrote on last edited by
          #4

          the call to unschedule needs to be synchronized.


          On two occasions I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. - Charles Babbage

          A 1 Reply Last reply
          0
          • E Ennis Ray Lynch Jr

            the call to unschedule needs to be synchronized.


            On two occasions I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. - Charles Babbage

            A Offline
            A Offline
            Ami Bar
            wrote on last edited by
            #5

            As I said, all the code runs on the same thread, so you don't have to synchronize. Ami

            E 1 Reply Last reply
            0
            • A Ami Bar

              As I said, all the code runs on the same thread, so you don't have to synchronize. Ami

              E Offline
              E Offline
              Ennis Ray Lynch Jr
              wrote on last edited by
              #6

              The code doesn't run on the same thread. Call backs from timers are on seperate threads.


              On two occasions I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. - Charles Babbage

              A M 2 Replies Last reply
              0
              • E Ennis Ray Lynch Jr

                The code doesn't run on the same thread. Call backs from timers are on seperate threads.


                On two occasions I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. - Charles Babbage

                A Offline
                A Offline
                Ami Bar
                wrote on last edited by
                #7

                The code is message based which is similar to Windows message loop. In Windows the GUI and the Timers are handled on the same thread. You can assume that the FileChanged method is called by a user button click. The click initiates a timer that its callback is called later on the same thread. However, synchronization is not an issue in the code. Ami

                1 Reply Last reply
                0
                • A Ami Bar

                  Look at the code below, from first observation it looks fine. However, it gets into an infinite loop. This code synchronizes a file changes between two machines (A and B). Every time there is a change in the file on A the whole file has to be passed to machine B. (The file doesn't change on machine B). In order to avoid the network traffic on every change, there is a mechanism that passes the file only if didn't it change for the past last minute. The Scheduler is an external class that is used as a timer. When Scheduler::Schedule is called the scheduled method will be called every interval until the Scheduler::Unschedule is called. All the methods of MyClass (including the constructor) executes on the same thread!!!

                  // Header
                  class MyClass
                  {
                  public:
                  MyClass();
                  void FileChanged();
                  void PassFile();

                  private:
                  long m_nTimerID;
                  Scheduler m_pScheduler;
                  };

                  // Class
                  MyClass::MyClass()
                  {
                  m_nTimerID = 0;
                  m_pScheduler = new Scheduler();
                  }

                  void MyClass::FileChanged()
                  {
                  if (0 != m_nTimerID)
                  {
                  // Unschedule the old timer
                  m_pScheduler->Unschedule(m_nTimerID);
                  }

                  // This line will call to MyClass::PassFile every 60 seconds from now
                  m\_nTimerID = m\_pScheduler->Schedule(60\*1000, &PassFile);
                  

                  }

                  MyClass::PassFile()
                  {
                  if (0 != m_nTimerID)
                  {
                  // Unschedule the old timer
                  m_pScheduler->Unschedule(m_nTimerID);
                  m_nTimerID = 0;
                  }

                  // Pass the file...
                  

                  }

                  Try to find out what's causing the infinite loop. I'll post the answer later. Hint: I used the ACE::HeapTimer (I don't remember the exact class name) to implement the Scheduler class. Ami

                  A Offline
                  A Offline
                  Ami Bar
                  wrote on last edited by
                  #8

                  The code assumes that the m_pScheduler->Schedule()’s valid return values are greater than zero. This assumption is incorrect. After a few times the FileChangedis called the method returns zero. The next time the FileChangedis called it will not unscheduled the previous timer and will create a new one. The timer that was not scheduled goes into an infinite loop, because it will never get unscheduled. The first time I noticed the loop I didn’t understand how this could happen, but I added logs. The next time I saw it I could see by the logs why I get into the loop. To fix the code replace the 0 with –1, which is a really invalid timer id. Ami

                  E 1 Reply Last reply
                  0
                  • A Ami Bar

                    The code assumes that the m_pScheduler->Schedule()’s valid return values are greater than zero. This assumption is incorrect. After a few times the FileChangedis called the method returns zero. The next time the FileChangedis called it will not unscheduled the previous timer and will create a new one. The timer that was not scheduled goes into an infinite loop, because it will never get unscheduled. The first time I noticed the loop I didn’t understand how this could happen, but I added logs. The next time I saw it I could see by the logs why I get into the loop. To fix the code replace the 0 with –1, which is a really invalid timer id. Ami

                    E Offline
                    E Offline
                    Ennis Ray Lynch Jr
                    wrote on last edited by
                    #9

                    I think think then that -1 should be replaced with a constant defined in the scheduler that represents an error rather than a magic number.


                    On two occasions I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. - Charles Babbage

                    1 Reply Last reply
                    0
                    • E Ennis Ray Lynch Jr

                      The code doesn't run on the same thread. Call backs from timers are on seperate threads.


                      On two occasions I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. - Charles Babbage

                      M Offline
                      M Offline
                      Mike Dimmick
                      wrote on last edited by
                      #10

                      Depends on the type of timer. A System.Windows.Forms.Timer is implemented with the SetTimer API, and therefore callbacks always occur on the UI thread (the one that created the form). A System.Threading.Timer is implemented using waitable timers and will fire events on any available thread pool thread. It does not make any attempt to synchronise with a currently-running callback - it will fire off another event (on another thread) even if a previous callback has not yet returned. A System.Timers.Timer wraps System.Threading.Timer and can be used to get back onto the appropriate thread for an object if you set the SynchronizingObject property. It derives from System.ComponentModel.Component so it can be dropped onto designer surfaces.

                      Stability. What an interesting concept. -- Chris Maunder

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups