.NET Windows服务需要使用STAThread [英] .NET Windows Service needs to use STAThread

查看:203
本文介绍了.NET Windows服务需要使用STAThread的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个Windows服务将被调出一些COM组件,所以我标记[STAThread]的主要功能。然而,当计时器触发,它报告MTA和COM调用失败。我该如何解决这个问题?

 使用系统;
使用System.Diagnostics程序;
使用System.ServiceProcess;
使用的System.Threading;
使用System.Timers;



命名空间MyMonitorService
{
    公共类MyMonitor:ServiceBase的
    {
        #区域会员
        私人System.Timers.Timer的定时器=新System.Timers.Timer的();
        #endregion

        #地区建设
        公共MyMonitor()
        {
            this.timer.Interval = 10000; //设置进行10秒
            this.timer.Elapsed + =新System.Timers.ElapsedEventHandler(this.timer_Elapsed);
        }
        #endregion

        私人无效timer_Elapsed(对象发件人,ElapsedEventArgs E)
        {
            EventLog.WriteEntry(MyMonitor的String.Format(线程模型:{0},Thread.CurrentThread.GetApartmentState()的ToString()),EventLogEntryType.Information);
        }

        #地区服务启动/停止
        [STAThread]
        公共静态无效的主要()
        {
            ServiceBase.Run(新MyMonitor());
        }

        保护覆盖无效的OnStart(字串[] args)
        {
            EventLog.WriteEntry(MyMonitor,我的监视服务启动,EventLogEntryType.Information);
            this.timer.Enabled = TRUE;
        }

        保护覆盖无效的onStop()
        {
            EventLog.WriteEntry(MyMonitor,我的监视服务已停止,EventLogEntryType.Information);
            this.timer.Enabled = FALSE;
        }
        #endregion
    }
}
 

解决方案

服务由Windows服务托管系统,它运行使用MTA线程运行。你无法控制这一点。你必须创建一个新的主题和的设置它的ApartmentState为STA ,做这个工作主题。

下面是一个类,扩展ServiceBase的,做这样的:

 公共部分类服务1:ServiceBase的
{
    私人System.Timers.Timer的定时器;

    公共服务1()
    {
        的InitializeComponent();
        定时器=新System.Timers.Timer的();
        this.timer.Interval = 10000; //设置进行10秒
        this.timer.Elapsed + =新System.Timers.ElapsedEventHandler(蜱);
    }

    保护覆盖无效的OnStart(字串[] args)
    {
        timer.Start();
    }

    私人无效蜱(对象发件人,ElapsedEventArgs E)
    {
        //创建一个线程,给它的工人,随它去吧
        //完成时(而不是IDisposable接口)被收集
        VAR线程=新主题(WorkerMethod);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        的onStop(); //终止计时器
    }

    私人无效WorkerMethod(对象状态)
    {
        //这里做你的工作在一个STA线程
    }

    保护覆盖无效的onStop()
    {
        timer.Stop();
        timer.Dispose();
    }
}
 

请注意这个code实际上并没有停止服务,停止计时。可能有许多仍然被多个线程完成的工作。举例来说,如果你的工作包括运行多个查询过一个大的数据库,你最终可能会崩溃,因为你必须在同一时间运行的线程太多。

在这样的情况下,我想创建STA线程集数(也许2倍的内核数量,开始了),该监视工作项目线程安全的队列。计时器滴答事件将负责装货,与急需人手完成的队列。

这一切都取决于你实际上在做每十秒钟,它是否应该在下一次计时器滴答,你应该做在这种情况下,等等等等来完成。

I have created a Windows Service that will be calling out to some COM components, so I tagged [STAThread] to the Main function. However, when the timer fires, it reports MTA and the COM calls fail. How can I fix this?

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
    }
}

解决方案

Services are run by the windows service hosting system, which runs using MTA threads. You can't control this. You have to create a new Thread and set its ApartmentState to STA, and do your work on this thread.

Here's a class that extends ServiceBase that does this:

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();
    }
}

Note this code doesn't actually stop the service, it stops the timer. There could be lots of work still being done on multiple threads. For instance, if your work consisted of running multiple queries off a large database you may end up crashing because you have too many threads running at the same time.

In a situation like this, I'd create a set number of STA threads (maybe 2x the number of cores to start off with) which monitor a thread-safe queue for work items. The timer tick event would be responsible for loading that queue with the work needing done.

It all depends on what you're actually doing every ten seconds, whether or not it should be completed the next time the timer ticks, what you should do in this situation, etc etc.

这篇关于.NET Windows服务需要使用STAThread的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆