我已经创建了一个
Windows服务,将调用一些COM组件,所以我标记了[STAThread]到主要功能.但是,当定时器触发时,它会报告MTA并且COM调用失败.如何解决这个问题?
- using System;
- using System.Diagnostics;
- using System.ServiceProcess;
- using System.Threading;
- using System.Timers;
- namespace MyMonitorService
- {
- public class MyMonitor : ServiceBase
- {
- #region Members
- private System.Timers.Timer timer = new System.Timers.Timer();
- #endregion
- #region Construction
- public MyMonitor ()
- {
- this.timer.Interval = 10000; // set for 10 seconds
- this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
- }
- #endregion
- private void timer_Elapsed (object sender,ElapsedEventArgs e)
- {
- EventLog.WriteEntry("MyMonitor",String.Format("Thread Model: {0}",Thread.CurrentThread.GetApartmentState().ToString()),EventLogEntryType.Information);
- }
- #region Service Start/Stop
- [STAThread]
- public static void Main ()
- {
- ServiceBase.Run(new MyMonitor());
- }
- protected override void OnStart (string[] args)
- {
- EventLog.WriteEntry("MyMonitor","My Monitor Service Started",EventLogEntryType.Information);
- this.timer.Enabled = true;
- }
- protected override void OnStop ()
- {
- EventLog.WriteEntry("MyMonitor","My Monitor Service Stopped",EventLogEntryType.Information);
- this.timer.Enabled = false;
- }
- #endregion
- }
- }
服务由使用MTA线程运行的Windows服务托管系统运行.你不能控制这个.你必须创建一个新的
Thread和
set its ApartmentState to STA,并在这个线程上做你的工作.
这是一个扩展ServiceBase的类:
- public partial class Service1 : ServiceBase
- {
- private System.Timers.Timer timer;
- public Service1()
- {
- InitializeComponent();
- timer = new System.Timers.Timer();
- this.timer.Interval = 10000; // set for 10 seconds
- this.timer.Elapsed += new System.Timers.ElapsedEventHandler(Tick);
- }
- protected override void OnStart(string[] args)
- {
- timer.Start();
- }
- private void Tick(object sender,ElapsedEventArgs e)
- {
- // create a thread,give it the worker,let it go
- // is collected when done (not IDisposable)
- var thread = new Thread(WorkerMethod);
- thread.SetApartmentState(ApartmentState.STA);
- thread.Start();
- OnStop(); // kill the timer
- }
- private void WorkerMethod(object state)
- {
- // do your work here in an STA thread
- }
- protected override void OnStop()
- {
- timer.Stop();
- timer.Dispose();
- }
- }
注意这个代码实际上并不停止服务,它会停止定时器.在多线程上可能还有很多工作要做.例如,如果您的工作包括从大型数据库运行多个查询,则可能会导致崩溃,因为您同时运行的线程太多.
在这样的情况下,我将创建一组STA线程(可能开始的两倍的核心数),它监视工作项的线程安全队列.定时器tick事件将负责在需要完成的工作中加载该队列.
这一切都取决于你每十秒钟实际做什么,无论是否在下一次定时器打勾时应该完成,在这种情况下应该做什么等等