BUG: The Elapsed event of the System.Timers.Timer class is not raised in a Windows service (842793)



The information in this article applies to:

  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0

SYMPTOMS

You can use the Microsoft .NET Framework to create a new Microsoft Windows service that contains a System.Timers.Timer object. When you run this new Windows service, the Elapsed event of the System.Timers.Timer class may not be raised.

CAUSE

Note In this section, the System.Timers.Timer object is referred to as the Timer object.

In the event handler for the Elapsed event of the Timer object, if you call the Stop method of the Timer object, the reference to the Timer object is lost. The garbage collector then reclaims the memory that is associated with the Timer object. Later, even if you call the Start method of the Timer object to raise the Elapsed event, the call does not work. The Elapsed event is not raised.

WORKAROUND

To work around this problem, obtain the hotfix in the following Microsoft Knowledge Base article:

900822 FIX: When a .NET Framework based application uses the System.Threading.Timer class, the timer event may not be signaled in the .NET Framework 1.1 S900822

Additionally, use a System.Threading.Timer object instead of the System.Timers.Timer object.

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed in the "Applies to" section.

MORE INFORMATION

Steps to reproduce the behavior

  1. Start Microsoft Visual Studio .NET.
  2. Use Microsoft Visual Basic .NET to create a Windows Service project that is named WinServ1. By default, the Service1.vb file is created.
  3. In Solution Explorer, rename Service1.vb as SimpleService.vb.
  4. Open the code view of the SimpleService.vb file.
  5. Replace the existing code with the following code:
    Imports System
    Imports System.ServiceProcess
    Imports System.Diagnostics
    Imports System.Timers
    
    Public Class SimpleService : Inherits ServiceBase
    
        Protected tmrMain As Timer
    
        Public Shared Sub Main()
            ServiceBase.Run(New SimpleService)
        End Sub
    
        Public Sub New()
            MyBase.New()
            CanPauseAndContinue = True
            ServiceName = "WinServ1"
            tmrMain = New Timer
        End Sub
    
        Protected Overrides Sub OnStart(ByVal args() As String)
            EventLog.WriteEntry("WinServ1 started")
            AddHandler tmrMain.Elapsed, AddressOf tmrMain_Elapsed
            AddHandler tmrMain.Disposed, AddressOf tmrMain_Disposed
            tmrMain.Interval = 1000
            ' Start raising the Elapsed event.
            tmrMain.Enabled = True
        End Sub
    
        Protected Sub tmrMain_Elapsed(ByVal source As Object, ByVal e As ElapsedEventArgs)
            EventLog.WriteEntry("WinServ1")
            ' Stop raising the Elapsed event.
            tmrMain.Stop()
            ' Force garbage collection to make sure that the garbage collector
            ' reclaims the memory that is associated with the tmrMain Timer object.
            GC.Collect()
            ' Start to raise the Elapsed event again.
            tmrMain.Start()
        End Sub
        Protected Sub tmrMain_Disposed(ByVal source As Object, ByVal e As EventArgs)
            EventLog.WriteEntry("WinServ1 timer disposed")
        End Sub
    
    End Class
  6. In Solution Explorer, click SimpleService.vb.
  7. On the View menu, click Properties Window to display the Properties window for the SimpleService.vb service.
  8. Switch to the design view of the SimpleService.vb service.
  9. At the bottom of the Properties window, click the Add Installer link to add the ProjectInstaller.vb file to your project. By default, the ServiceProcessInstaller1 object and the ServiceInstaller1 object are created.
  10. In the Properties window for the ServiceInstaller1 object, set the StartType property to Automatic.
  11. In the Properties window for the ServiceProcessInstaller1 object, set the Account property to LocalSystem.
  12. In Solution Explorer, right-click the WinServ1 project, and then click Properties. The WinServ1 Property Pages dialog box appears.
  13. In the Startup object box, select Sub Main, and then click OK.
  14. On the Build menu, click Build Solution to create the WinServ1.exe file.
  15. Install the Windows service that you created. To do this, run the following command at a Visual Studio .NET command prompt:

    installutil Path\WinServ1.exe

    Note Path is a placeholder for the absolute file path of the WinServ1.exe file that you created in step 14.
  16. Restart your computer.

    The WinServ1 service starts to run and then writes information to the application log of Event Viewer every second. You may soon notice that the WinServ1 service does not write information to the application log. This behavior indicates that the Elapsed event is not being raised.

Modification Type:MinorLast Reviewed:2/18/2006
Keywords:kbtshoot kbBug kbSample kbcode kbServiceProcess kbTimer KB842793 kbAudDeveloper