微软对此在这两篇文章那个中给出了相应的解决方案,
http://support.microsoft.com/kb/820639/zh-cn,
http://support.microsoft.com/kb/842793/zh-cn。
实际上就是在使用Windows.Forms命名空间中的timer无效时则使用System.Timers中的组件,再不行的话使用Threading中的Timer组件。我遇到的是第一种情况,通过使用System.Timers中的Timer,问题解决了。
症状
您添加到 Windows 服务 Microsoft WindowsForms 计时器组件。 启用计时器, 然后您设置计时器以引发事件的间隔。 计算机, 上安装 Windows 服务, 然后您启动服务。 不引发 计时器 事件在 Windows 服务。
注意 : WindowsForms 计时器组件位于 System.Windows.Forms 命名空间中。
原因
WindowsForms 计时器组件用于 WindowsForms 环境,不用于服务器环境。 计时器如果在 Windows 服务使用时, 可能不引发事件。
解决方案
要解决此问题, 使用服务器计时器时让命名空间 System.Timers 代替 System.Windows.Forms 命名空间。 要这样做, 请按照下列步骤操作:
1. |
在要删除 Service 1 类命令窗口运行以下命令:
installutil /u WindowsService1.exe
注意 WindowsService1.exe 位于您的项目文件夹下 bin 文件夹中。 添加路径是您 WindowsService1.exe。 |
2. |
切换到 Windows 服务项目。 |
3. |
在 Service 1 设计器窗口, 单击 Timer 1 控件。 |
4. |
按 DELETE 键从设计器窗口中删除该 Timer 1 控件。 |
5. |
在工具栏上, 单击 组件 选项卡。 |
6. |
从工具栏, 将 Timer 控件拖到设计器窗口。 |
7. |
双击设计器窗口以查看代码窗口上 Timer 1 控件。 |
8. |
Timer 1 控件的 Tick 事件处理程序中移动到的 Timer 1 控件 Elapsed 事件处理程序代码 |
9. |
移除 Tick 事件处理程序。 |
10. |
在 生成 菜单上, 单击 BuildSolution@@@ 。 |
11. |
在命令窗口运行以下命令:
installutil WindowsService1.exe
|
12. |
在 管理工具 菜单上, 单击 服务 。 |
13. |
右击 Service 1 , 然后单击 开始 。 |
14. |
等待几秒钟, 右击 Service 1 , 然后单击 停止 。 |
15. |
打开, C:\sample.txt 文件, 然后注意文本。
以 开始 和 停止 Tick 文本显示。 |
状态
此行为是设计使然。
更多信息
再现问题的步骤
1. |
启动 MicrosoftVisualStudio.NET。 |
2. |
通过使用 MicrosoftVisualBasic.NET 或 MicrosoftVisualC # .NET 打开一个新 Windows 服务项目。
默认情况下, 创建 Service 1 。 |
3. |
在工具箱中, 单击 WindowsForms 选项卡。 |
4. |
将一个 Timer 控件从工具箱拖到 Service 1 设计器窗口。 |
5. |
在设计器窗口, 双击 Timer 1 控件。
显示 Service 1 代码窗口。 |
6. |
如果您使用 VisualC # .NET, 将以下语句添加到开头的代码:
using System.IO;
|
7. |
以下代码添加到 Service 1 类的 OnStart 过程。
VisualBasic.NET 代码
'Set the interval of the timer to 3 seconds.
Timer1.Interval = 3000
Timer1.Enabled = True
'Open the sample.txt file in append mode.
FileOpen(1, "C:\sample.txt", OpenMode.Append)
'Print text to the "C:/sample.txt file.
Print(1, "Start")
FileClose()
VisualC # .NET 代码
//Set the interval of timer to 3 seconds.
timer1.Interval =3000;
//Enable the timer.
timer1.Enabled =true;
//Append the text to the sample file.
StreamWriter writer =File.AppendText(@"C:\sample.txt");
writer.WriteLine("Start");
writer.Close();
|
8. |
以下代码添加到 Service 1 类的 OnStop 过程。
VisualBasic.NET 代码
'Open the C:\sample.txt file in append mode.
FileOpen(1, "C:\sample.txt", OpenMode.Append)
'Print the text 'Stop' to the C:\sample.txt file.
Print(1, "Stop")
FileClose()
VisualC # .NET 代码
//Append the text Stop to the C:\sample.txt file.
StreamWriter writer =File.AppendText(@"C:\sample.txt");
writer.WriteLine("Stop");
writer.Close();
|
9. |
将以下代码添加到 Timer 1 组件的 Tick 事件。
VisualBasic.NET 代码
'Set the enabled property to false.
Timer1.Enabled = False
'Open the C:\sample.txt file in append mode.
FileOpen(1, "C:\sample.txt", OpenMode.Append)
'Print the text 'Tick' to the C:\sample.txt file.
Print(1, "Tick")
FileClose()
'Enable the timer.
Timer1.Enabled = True
VisualC # .NET 代码
//Set the enable property to false.
timer1.Enabled =false;
//Append the text Tick to the C:\sample.txt file.
StreamWriter writer =File.AppendText(@"C:\sample.txt");
writer.WriteLine("Tick");
writer.Close();
timer1.Enabled =true;
|
10. |
在 视图 菜单上, 单击 设计器 。 |
11. |
右击 设计器 , 然后单击 添加 Installer 。
默认情况下, ServiceInstaller 1 和 ServiceProcessInstaller1 创建。 |
12. |
ServiceInstaller 1 , 右击, 然后单击 属性 。 |
13. |
将 DisplayName 属性设置为 Service 1 。
注意 最好要将 ServiceName 属性设为 Service 1 。 |
14. |
右击 ServiceProcessInstaller1 , 然后单击 属性 。 |
15. |
在属性窗口, ServiceProcessInstaller1 将以 LocalSystem 帐户 属性。 |
16. |
在 生成 菜单上, 单击 BuildSolution@@@ 。 |
17. |
开始 , 依次 运行 。 |
18. |
在运行窗口, 在 打开 框中, 键入 cmd , 然后按 ENTER 键。 |
19. |
在命令提示符下, 运行以下命令:
installutil WindowsService1.exe
注意 如果使用任何其他服务具有相同名称不安装您 Service 1 服务。 |
20. |
完成安装步骤后, AdministrativeTools , 控制面板中单击, 然后单击 服务 。 |
21. |
在服务窗口, 右击 Service 1 , 依次 开始 。 |
22. |
等待几秒钟, 右击 Service 1 , 然后单击 停止 。 |
23. |
打开 C:\sample.txt 文件。
显示文本 StartStop 。 不引发 Timer 1 Tick 事件, 并且不打印到 C:\sample.txt 文件 Tick 文本。 |
以下是本人编写的一个例子:
Program.cs
Code
1using System.Collections.Generic;
2using System.ServiceProcess;
3using System.Text;
4using EmailPOP3;
5
6namespace WinService
7{
8 static class Program
9 {
10 /**//// <summary>
11 /// 应用程序的主入口点。
12 /// </summary>
13 static void Main()
14 {
15
16 ServiceBase[] ServicesToRun;
17
18 // 同一进程中可以运行多个用户服务。若要将
19 // 另一个服务添加到此进程中,请更改下行以
20 // 创建另一个服务对象。例如,
21 //
22 // ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
23 //
24 ServicesToRun = new ServiceBase[] { new Service1() };
25
26 ServiceBase.Run(ServicesToRun);
27 }
28 }
29
30}
ProjectInstaller.cs
Code
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Configuration.Install;
5
6namespace WinService
7{
8 [RunInstaller(true)]
9 public partial class ProjectInstaller : Installer
10 {
11 public ProjectInstaller()
12 {
13 InitializeComponent();
14 }
15 }
16}
ProjectInstaller.Designer.cs
Code
1namespace WinService
2{
3 partial class ProjectInstaller
4 {
5 /**//// <summary>
6 /// 必需的设计器变量。
7 /// </summary>
8 private System.ComponentModel.IContainer components = null;
9
10 /**//// <summary>
11 /// 清理所有正在使用的资源。
12 /// </summary>
13 /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
14 protected override void Dispose(bool disposing)
15 {
16 if (disposing && (components != null))
17 {
18 components.Dispose();
19 }
20 base.Dispose(disposing);
21 }
22
23 组件设计器生成的代码#region 组件设计器生成的代码
24
25 /**//// <summary>
26 /// 设计器支持所需的方法 - 不要
27 /// 使用代码编辑器修改此方法的内容。
28 /// </summary>
29 private void InitializeComponent()
30 {
31 this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
32 this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
33 //
34 // serviceProcessInstaller1
35 //
36 this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
37 this.serviceProcessInstaller1.Password = null;
38 this.serviceProcessInstaller1.Username = null;
39 //
40 // serviceInstaller1
41 //
42 this.serviceInstaller1.ServiceName = "pop3Service";
43 this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
44 //
45 // ProjectInstaller
46 //
47 this.Installers.AddRange(new System.Configuration.Install.Installer[] {
48 this.serviceProcessInstaller1,
49 this.serviceInstaller1});
50
51 }
52
53 #endregion
54
55 private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
56 private System.ServiceProcess.ServiceInstaller serviceInstaller1;
57 }
58}
Service1.cs
Code
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Data;
5using System.Diagnostics;
6using System.ServiceProcess;
7using System.Text;
8using System.Threading;
9
10using EmailPOP3;
11
12namespace WinService
13{
14 partial class Service1 : ServiceBase
15 {
16 private System.Timers.Timer timer1;
17
18 public Service1()
19 {
20 InitializeComponent();
21 }
22
23 protected override void OnStart(string[] args)
24 {
25 this.timer1.Enabled = true;
26 this.timer1.Start();
27 }
28
29 protected override void OnStop()
30 {
31 // TODO: 在此处添加代码以执行停止服务所需的关闭操作。
32 this.timer1.Stop();
33 }
34
35 //private void timer1_Tick(object sender, EventArgs e)
36 //{
37 // POPPersistent pop3 = new POPPersistent();
38
39 // pop3.OperationEmail();
40 //}
41
42 /**//// <summary>
43 /// 监视索引
44 /// </summary>
45 /// <param name="sender"></param>
46 /// <param name="e"></param>
47 private void timer1_Elapsed(object sender, EventArgs e)
48 {
49
50 POPPersistent pop3 = new POPPersistent();
51
52 pop3.OperationEmail();
53 }
54 }
55}
56
Service1.Designer.cs
Code
1namespace WinService
2{
3 partial class Service1
4 {
5 /**//// <summary>
6 /// 必需的设计器变量。
7 /// </summary>
8 private System.ComponentModel.IContainer components = null;
9
10 /**//// <summary>
11 /// 清理所有正在使用的资源。
12 /// </summary>
13 /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
14 protected override void Dispose(bool disposing)
15 {
16 if (disposing && (components != null))
17 {
18 components.Dispose();
19 }
20 base.Dispose(disposing);
21 }
22
23 组件设计器生成的代码#region 组件设计器生成的代码
24
25 /**//// <summary>
26 /// 设计器支持所需的方法 - 不要
27 /// 使用代码编辑器修改此方法的内容。
28 /// </summary>
29 private void InitializeComponent()
30 {
31 this.timer1 = new System.Timers.Timer();
32 ((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
33 //
34 // timer1
35 //
36 this.timer1.AutoReset = false;
37 this.timer1.Enabled = true;
38 this.timer1.Interval = 20000;
39 this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Elapsed);
40 //
41 // Service1
42 //
43 this.ServiceName = "Service1";
44 ((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
45
46 }
47
48 #endregion
49
50 //private System.Windows.Forms.Timer timer1;
51 }
52}
53
其中,POPPersistent类及其方法OperationEmail()是要关联的程序。