Mit einem timer in einem Windows-Dienst - elapsed-Ereignis-handler hält brennen noch, wenn der timer deaktiviert ist
Ich habe viel gelesen von den Beiträgen im Zusammenhang mit Windows-Diensten und die Verwendung von Timern, aber ich habe nicht gefunden, einen Grund, warum meine event-handler wird trotzdem ausgelöst werden kann. Kann jemand mich in die richtige Richtung? Ich will wissen warum das ist geschehen, damit ich verstehe, wie dies zu vermeiden in der Zukunft.
Edit: Das onError-event-handler wird nie aufgerufen (oder ich gesehen haben, das Ereignis in die Ereignis-log).
Timer: System.Timer.Timer
ServiceBase: System.ServiceProcess.ServiceBase
Hier ist die abstrakte Klasse:
public abstract class ABCService : ServiceBase
{
//Members
protected Timer invocationTimer;
protected Timer wellnessTimer;
protected FileSystemWatcher fsw;
//Constructors
protected ABCService()
{
invocationTimer = new Timer();
wellnessTimer = new Timer();
fsw = null;
invocationTimer.AutoReset = false;
invocationTimer.Interval = 30000; //30 seconds
invocationTimer.Elapsed += new ElapsedEventHandler(invocationTimer_Elapsed);
wellnessTimer.AutoReset = false;
wellnessTimer.Elapsed += new ElapsedEventHandler(wellnessTimer_Elapsed);
}
//Methods
protected void invocationTimer_Elapsed(object o, ElapsedEventArgs args)
{
try
{
//log to event log
invocationTimer.Stop();
if ((new FileInfo(fsw.Path + "\\" + fsw.Filter)).Exists)
{
onCreated(this, new FileSystemEventArgs(WatcherChangeTypes.Created, fsw.Path, fsw.Filter));
}
}
catch (Exception x)
{
onError(this, new ErrorEventArgs(x));
}
}
protected void wellnessTimer_Elapsed(object o, ElapsedEventArgs args)
{
try
{
//log to event log
wellnessTimer.Stop();
wellnessTimer.Interval = 60000; //ms
if (fsw != null)
{
fsw.Dispose();
}
fsw = new FileSystemWatcher(ConfigurationManager.AppSettings["pathKey"], ConfigurationManager.AppSettings["filterKey"]);
invocationTimer.Start();
}
catch (Exception x)
{
onError(this, new ErrorEventArgs(x));
}
}
protected abstract void onCreated(object o, FileSystemEventArgs args);
protected virtual void onError(object o, ErrorEventArgs args)
{
//log to event log
wellnessTimer.Start();
}
protected override void OnStart(string[] args)
{
//log to event log
wellnessTimer.Interval = 5000; //5 seconds
wellnessTimer.Start();
}
protected override void OnStop()
{
//log to event log
wellnessTimer.Stop();
}
}
Hier ist eine Instanz der Klasse:
public partial class Service1 : ABCService
{
//Members
private static object locket = new object();
private static DateTime LAST_RUN_TIME = DateTime.Now.AddSeconds(-10);
//Constructors
public Service1()
{
InitializeComponent();
}
//Methods
protected override void onCreated(object o, FileSystemEventArgs args)
{
lock (locket)
{
//log to event log
if ((DateTime.Now - LAST_RUN_TIME).Seconds >= 10)
{
//do stuff
}
else
{
//log to event log
invocationTimer.Stop();
invocationTimer.Start();
}
}
}
}
Hier ist der automatisch generierte code für die partielle Klasse:
partial class Service1
{
///<summary>
///Required designer variable.
///</summary>
private System.ComponentModel.IContainer components = null;
///<summary>
///Clean up any resources being used.
///</summary>
///<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
///<summary>
///Required method for Designer support - do not modify
///the contents of this method with the code editor.
///</summary>
private void InitializeComponent()
{
//
//Service1
//
this.ServiceName = "Service1";
}
#endregion
}
Also, was genau ist passiert? Ich freu mich auf mein event-log und ich sehe, dass einmal pro minute die wellnessTimer event-handler aufgerufen wird.
Hier ist, was ich denke passiert, aber ich bin offensichtlich falsch:
1. Service is started via MMC
2. OnStart() method is invoked
3. wellnessTimer interval is set to 5 seconds
4. wellnessTimer start method is invoked
5. wellnessTimer_Elapsed event handler is invoked
6. wellnessTimer stop method is invoked
7. wellnessTimer interval is set to 5 minutes
8. invocationTimer start method is invoked
9. 30 seconds later, the invocationTimer_Elapsed method is invoked
10. invocationTimer stop method is invoked
Zu diesem Zeitpunkt beide Timer sollte noch vorhanden sein, damit diese Instanz, die aber deaktiviert werden sollten. Ich gedebuggt dieses über attach to process in Visual Studio 2010 und markiert eine ID für das Objekt (sender) übergeben wird in die event-Handler. Es ist das gleiche Objekt wie die Instanz. Auch die beiden Timer in den Fenster hatte, deren enabled-Eigenschaft auf false festgelegt.
Macht mich das, was ich bin mit der Vererbung falsch, oder was ist Los mit threading. Ich bin nicht der beste in diesen Sachen, aber wenn es wegen Ihnen bitte lassen Sie mich wissen, damit ich lernen kann.
Danke an alle im Voraus.
Edit #2: Hier einige Daten zu verfolgen...
'o' steht für das übergebene Objekt in den event-handler
ABCService() method invoked <--
ABCService() method invoked -->
Service1() method invoked <--
Service1() method invoked -->
OnStart() method invoked <--
OnStart() method invoked -->
wellnessTimer_Elapsed() method invoked <--
((System.Timers.Timer) o).Enabled = False
((System.Timers.Timer) o).Interval = 5000
this.wellnessTimer.Enabled = False
this.wellnessTimer.Interval = 5000
wellnessTimer_Elapsed() method invoked -->
invocationTimer_Elapsed() method invoked <--
((System.Timers.Timer) o).Enabled = False
((System.Timers.Timer) o).Interval = 30000
this.invocationTimer.Enabled = False
this.invocationTimer.Interval = 30000
invocationTimer_Elapsed() method invoked -->
wellnessTimer_Elapsed() method invoked <--
((System.Timers.Timer) o).Enabled = False
((System.Timers.Timer) o).Interval = 60000
this.wellnessTimer.Enabled = False
this.wellnessTimer.Interval = 60000
wellnessTimer_Elapsed() method invoked -->
invocationTimer_Elapsed() method invoked <--
((System.Timers.Timer) o).Enabled = False
((System.Timers.Timer) o).Interval = 30000
this.invocationTimer.Enabled = False
this.invocationTimer.Interval = 30000
invocationTimer_Elapsed() method invoked -->
Die richtige Richtung ist hier.
Sie können versuchen, die aufrufende Timer.Dispose()
Aye, ich habe gelesen, dass auch. Aber ich werde mit Ihnen einverstanden. Diese Anwendung wurde entwickelt, um kontinuierlich laufen; der Timer sollte nicht brennen, die auf einem vorbestimmten Intervallen.
Ich aktualisierte mein code entsprechend der Ereignis-Protokollierung. Die onError-event-handler wird nie aufgerufen.
InformationsquelleAutor The Cog | 2012-07-24
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vom MSDN ' s Bemerkungen über die Timer-Klasse:
So können Sie etwas tun, wie dieses in Ihrem event-handler, um zu verhindern, dass Sie es ausgeführt haben, nachdem der timer deaktiviert wurde:
InformationsquelleAutor Thomas C. G. de Vilhena
Erleben Sie das problem mit den code genau wie Sie, oder würde es davon abhängig sein, code:
Basierend auf dem, was ich lese aus dem code, der wellness-timer ausgelöst wird, der alle 60 Sekunden, wenn es auf einen Fehler auf der onCreated nennen. Wenn dies tun, Datei-Operationen, die eine Sache, die schreit, ist die Sicherheits-Berechtigungen für das Konto der Dienst ausgeführt wird.
Wenn man eine Ausnahme, die Ausgabe an das Ereignisprotokoll oder eine log-Datei. Verhalten einer Ausnahme führt schnell zu unübersichtlichen Situationen, insbesondere dort, wo es nicht so bequem, um hook up einen debugger.
ok, ein paar Dinge: 1.) Hast du eine log-Ausgabe in Ihrem onCreated handler? Damit es läuft, ohne eine Ausnahme zu werfen. 2) Die Prüfung sieht wie Sie beabsichtigen, etwas zu überprüfen, alle 10 Sekunden? Sie werden wollen ."TotalSeconds. .Sekunden geben Sie die Sekunden-Komponente der Zeit Unterschied. Wäre kein problem, wenn etwas nahm zwischen x:00 bis x:09 lang. wobei x=1 minute oder mehr. Diese Annahme kann die Ursache für verrückte Fehler, wenn in anderen Szenarios verwendet, nicht unbedingt diese. 🙂
Ich war in der Lage, um es herauszufinden, aber ich musste das schreiben. Es ist völlig weht mir ein, warum, wenn alle Timer deaktiviert sind, sind Sie noch Auslösung der elasped Veranstaltung. Ich werde nach der neu geschriebene code, sowie die legacy-code zum Vergleich. Vielleicht wird dies dazu führen, eine definitive Antwort und ich will endlich wissen, warum! 🙂 Vielen Dank für Ihre Hilfe! 1) ja, tatsächlich habe ich auskommentiert, die gesamten "Innereien" des onCreated event-handler bei der Implementierung von Klassen. 2) Das Ziel ist die Verwendung einer erweiterten FileSystemWatcher und binden Sie die onError-event-handler in es so ich das beheben kann seinen schlechten Zustand.
InformationsquelleAutor Steve Py