web-dev-qa-db-fra.com

Service Windows avec minuterie

J'ai créé un service Windows avec timer dans c # .net. cela fonctionne bien pendant que je débogue/construis le projet dans visual studio mais il ne fonctionne pas après l’installation.

Quelle pourrait être la raison derrière cela?

code: 

public partial class Service1 : ServiceBase
{
        FileStream fs;
        StreamWriter m_streamWriter;
        Timer tm = new Timer();

        public Service1()
        {
            InitializeComponent();

            this.ServiceName = "timerservice";

            tm.Interval = 2000;
            tm.Tick += new EventHandler(PerformOperations);
            tm.Start();

            fs = new FileStream(@"c:\mcWindowsService.txt", FileMode.OpenOrCreate, FileAccess.Write);

            m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
        }

        private void PerformOperations(object sener, EventArgs e)
        {
            //StreamWriter swr = new StreamWriter("c:\\test_from_database.txt",true);

            try
            {
                OdbcConnection con = new OdbcConnection("DSN=liquor_data");

                OdbcDataAdapter adp = new OdbcDataAdapter("", con);

                DataSet ds = new DataSet();

                string sql = "select * from item_group";
                adp.SelectCommand.CommandText = sql;

                adp.Fill(ds, "item_group");

                foreach (DataRow dr in ds.Tables["item_group"].Rows)
                {
                    //      swr.Write(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");

                    //Console.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
                    m_streamWriter.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
                }

                m_streamWriter.Flush();
            }

            catch (Exception ex)
            {
                // swr.Write("Error :"+ ex.Message + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n"); }
            }
        }
    }
29
Nitin Kabra

Première approche avec Windows Service n'est pas facile ..

Il y a longtemps, j'ai écrit un service C #.

C'est la logique de la classe Service (testée, fonctionne bien):

namespace MyServiceApp
{
    public class MyService : ServiceBase
    {
        private System.Timers.Timer timer;

        protected override void OnStart(string[] args)
        {
            this.timer = new System.Timers.Timer(30000D);  // 30000 milliseconds = 30 seconds
            this.timer.AutoReset = true;
            this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
            this.timer.Start();
        }

        protected override void OnStop()
        {
            this.timer.Stop();
            this.timer = null;
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            MyServiceApp.ServiceWork.Main(); // my separate static method for do work
        }

        public MyService()
        {
            this.ServiceName = "MyService";
        }

        // service entry point
        static void Main()
        {
            System.ServiceProcess.ServiceBase.Run(new MyService());
        }
    }
}

Je vous recommande d'écrire votre travail de service réel dans une méthode statique distincte (pourquoi pas, dans une application console ... ajoutez-y simplement une référence), pour simplifier le débogage et nettoyer le code de service.

Assurez-vous que l'intervalle est suffisant et écrivez log SEULEMENT dans les remplacements OnStart et OnStop.

J'espère que cela t'aides!

55
T-moty

Vous devez mettre votre code principal sur la méthode OnStart.

Cette autre SO réponse de la mienne pourrait aider.

Vous aurez besoin de mettre du code pour activer le débogage dans visual-studio tout en maintenant votre application valide en tant que service Windows. Cet autre SO fil couvre la question du débogage d’un service Windows.

MODIFIER:

Veuillez également consulter la documentation disponible ici pour la méthode OnStart sur MSDN où vous pouvez lire ceci:

N'utilisez pas le constructeur pour effectuer un traitement qui devrait être dans OnStart. Utilisez OnStart pour gérer l’initialisation de votre service. Le Le constructeur est appelé lorsque l'exécutable de l'application s'exécute, pas quand le service fonctionne. L'exécutable s'exécute avant OnStart. Lorsque vous continue, par exemple, le constructeur n'est pas appelé à nouveau parce que le SCM contient déjà l'objet en mémoire. Si OnStop libère des ressources alloué dans le constructeur plutôt que dans OnStart, le nécessaire les ressources ne seraient plus créées la deuxième fois que le service est appelé.

7
Luis Quijada

Voici un exemple de travail dans lequel l'exécution du service est démarrée dans OnTimedEvent du minuteur, implémenté en tant que délégué dans la classe ServiceBase et la logique du minuteur est encapsulée dans une méthode appelée SetupProcessingTimer (): 

public partial class MyServiceProject: ServiceBase
{

private Timer _timer;

public MyServiceProject()
{
    InitializeComponent();
}

private void SetupProcessingTimer()
{
    _timer = new Timer();
    _timer.AutoReset = true;
    double interval = Settings.Default.Interval;
    _timer.Interval = interval * 60000;
    _timer.Enabled = true;
    _timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // begin your service work
    MakeSomething();
}

protected override void OnStart(string[] args)
{
    SetupProcessingTimer();
}

...
}

L'intervalle est défini dans app.config en quelques minutes:

<userSettings>
    <MyProject.Properties.Settings>
        <setting name="Interval" serializeAs="String">
            <value>1</value>
        </setting>
    </MyProject.Properties.Settings>
</userSettings>
0
Uwe Köhler