Frage

VB.NET 2010, .NET 4

Hallo an alle,

Ich habe ein System.Timers.Timer Objekt, das einige Arbeit auf dem abgelaufenen Ereignisse tut:

Private Sub MasterTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles MasterTimer.Elapsed
    MasterTimer.Enabled = False
    '...work...
    MasterTimer.Enabled = True
End Sub

Mein Problem ist, dass die Arbeit, dass es manchmal tut stecken bleibt. Ein Teil der Arbeit ist die serielle Kommunikation, so dass es steckt Warte bekommen könnte auf eine Antwort von etwas. Ich habe bereits meine serielle Kommunikation Code ein wenig modifiziert, um hoffentlich das Problem zu lösen. Allerdings ist dieser Timer im Grunde der Herzschlag einer Produktionssteuerungsanwendung und es ist sehr schlecht, wenn es aus irgendeinem Grunde zu stoppen ist. Ich dachte, dass es schön sein könnte, in einem ausfallsicheren Timeout zu setzen, so dass, wenn die „Arbeit“ zu lange dauert, kann der Timer selbst wieder aktivieren und versuchen Sie es erneut. Ich dachte an so etwas wie folgt aus:

Bewegen Sie die Arbeit in einem Unterprogramm und erstellen Sie einen Delegaten:

Private Delegate Sub WorkDelegate()
Private Sub Work()
   '...work...
End Sub

Rufen Sie die Arbeit durch den Delegaten aufrufen und verwenden Sie dann WaitOne (Timeout) auf dem IAsyncResult ein Timeout angeben:

Private Sub MasterTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles MasterTimer.Elapsed
    MasterTimer.Enabled = False
    Dim workDel as New WorkDelegate(AddressOf Work)
    Dim result as IAsyncResult = workDel.BeginInvoke
    result.AsyncWaitHandle.WaitOne(CInt(MasterTimer.Interval))
    MasterTimer.Enabled = True
End Sub

Aber meine Frage ist: Wäre diese Ursache ein Problem, wenn Arbeit () wirklich stecken irgendwo war? In, dass es ein Unterprogramm erneut eingeben, die bereits ausgeführt wird? Gibt es eine Möglichkeit zum Abbruch der Arbeit (), wenn es nicht nach dem Timeout beendet hat? Mit anderen Worten, nicht mehr nur die Ausführung der Arbeit (), wenn result.IsCompleted falsch ist nach WaitOne?

Ich weiß nicht wirklich das Zeug sehr gut verstehen, so, keine Kommentare würden sehr geschätzt werden. Vielleicht gibt es eine ganz andere Art und Weise dies zu nähern, dass ich weiß, über nicht?

Vielen Dank im Voraus!

Ich möchte etwas hinzufügen:

Auch wenn ich beabsichtige, einige umschreibt laut Hans' Vorschläge zu tun, hatte geplant ich schon einen Tag zu testen, um zu versuchen, die Quelle dieses Fehlers zu isolieren. Bisher hat es trat nur bei der kompilierten Anwendung ausgeführt wird. Ich habe heute ausgegeben (und einige gestern) versucht, das Einfrieren zu reproduzieren, während im Debug-Modus ausgeführt wird, so dass vielleicht könnte ich ein paar Haltepunkte und herauszufinden, fügen Sie, was los ist. Bisher hat sich das Programm nicht im Debug-Modus eingefroren. Ich frage mich nur, ob es etwas anderes über die Debug-Umgebung ist, die dies erklären könnte. Es könnte nur sein, dass ich „Glück“ bin, aber ich habe es wohl dreimal die durchschnittliche Zeitdauer, nach der das Programm fror ausgeführt werden, wenn die ausführbare Datei läuft ... Noch einmal, ich ziemlich unwissend bin, aber gibt es etwas, einzigartig über die Debug-Umgebung, die dies erklären könnte? Ich werde wieder aktualisieren, wenn es friert.

War es hilfreich?

Lösung

Das geht schief auf der ersten Zeile des Codes. Die System.Timers.Timer Klasse ist ziemlich eklig, es gibt absolut keine Garantie, dass Call-Stop () wird einen weiteren Anruf verhindern. Der Timer verwendet ThreadPool.QueueUserWorkItem die verstrichene Ereignishandler Anruf zu tätigen. Wenn der Threadpool besetzt ist, kann dies mehrere Anrufe am Ende Schlange steht, wartete grünes Licht aus den TP-Scheduler zu bekommen anfangen zu laufen. wird der Timer nicht zu stoppen, diese wartenden Threads nicht ausgeführt werden. Ohne eine Sperre verwendet wird, werden diese Fäden aufeinander Schritt schlecht und vermasseln Ihren Kommunikationszustand.

Ein sicherer ist System.Threading.Timer mit einer Periode von Null, so dass Sie nur ein Rückruf bekommen. Laden Sie den Timer mit seinen Change () -Methode.

Ein Delegierter des BeginInvoke () -Methode aufrufen und dann blockiert darauf Abschluss macht keinen Sinn. Rufen Sie einfach Invoke (). Speichert man aus der Verbrennung von einem anderen Thread auf.

Ja, wenn die ‚Arbeit‘ Methode nie kehrt dann haben Sie ein Problem. Unlösbarer ein.

Viele dieser Misere könnten verschwinden, wenn Sie mit Polling vermeiden, um zu sehen, ob es gibt zur Verfügung, alles auf dem seriell Port. Lassen Sie es Ihnen sagen, dass es etwas lohnt sich geht. Es stellt sich die DataReceived Ereignis, auf einem Threadpool-Thread, wann immer es gibt mindestens ein Byte im Empfangspuffer. seine Eigenschaft Writetimeout zu verwenden ist auch eine hervorragende Möglichkeit bekommen, stecken zu vermeiden, wenn etwas nicht stimmt mit der Protokoll-Kommunikation ist oder das Gerät. Widmet ein Thema und machen Blockierung lesen funktioniert gut auch nennt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top