Forum: PC-Programmierung System.Windows.Forms.Timer und Tread.Sleep in C#


von Leonhard (Gast)


Lesenswert?

Guten Morgen,

für eine GUI Anwendung benutze ich einen WIndows.Forms.Timer der 
zyklisch mi 1 Sekunde läuft. Innerhalb dieses Timers verwende ich noch 
die Funktion Thread.Sleep(...). Das mit dem Thread.Sleep gefällt mir 
nicht. Wie könnte man eine Verzögerung innerhalb einer 
WIndows.Forms.Timers realisieren?
Das TimerEvent synchronisiere mit der GUI Applikation anhand der Invoke 
Methode.

von Borislav B. (boris_b)


Lesenswert?

Warum nimmst du nicht gleich einen zweiten Thread?
Das wäre glaubich einfacher...

Etwa so:
1
mMustWork = true;
2
var thread = new Thread(MyThread);
3
thread.Start();
4
5
6
private void MyThread()
7
{
8
 while(mMustWork)
9
 {
10
   Thread.Sleep(1000);
11
   DoStuff();
12
   Thread.Sleep(20);
13
   DoMoreStuff();
14
 }
15
}

: Bearbeitet durch User
von Leonhard (Gast)


Lesenswert?

Könnten da Probleme im laufenden Betrieb entstehen, wenn Thread.Sleep im 
System.Windows.Forms.Timer verwendet wird?

von nicht"Gast" (Gast)


Lesenswert?

Moin,

da der timer_tick im Thread der GUI läuft, tauchen bei Wartezeiten auch 
die üblichen Probleme auf.

von Halbkreisgewölbter (Gast)


Lesenswert?

Leonhard schrieb:
> Das TimerEvent synchronisiere mit der GUI Applikation anhand der Invoke
> Methode.

Das solltest du nicht machen, weil

nicht"Gast" schrieb:
> der timer_tick im Thread der GUI läuft

Bitte beschreibe doch mal das komplette Problem - einschließlich des 
Zwecks der Verzögerung - auf einer allgemeinen Ebene (ganz unabhängig 
von möglichen spezifischen Implementierungen, die du bereits ins Auge 
gefasst hast).

von Leonhard (Gast)


Lesenswert?

Innerhalb des Timers (zyklisch 1 Sekunde) sollen im Abstand von 20ms 
Nachrichten gesendet werden.

Beispiel mit 3 Nachrichten:

Timer startet zyklisch mit 1 Sekunde

--> zyklische Timer
    --> Nachricht 1 senden
    --> 20 ms warten
    --> Nachricht 2 senden
    --> 20ms warten
    --> Nachricht 3 senden
    --> 20ms warten

von Leonhard (Gast)


Lesenswert?

Ich habe im letzten Beitrag noch was vergessen.

Beispiel mit 3 Nachrichten:

--> Timer startet zyklisch mit 1 Sekunde

--> zyklische Timer
    --> Nachricht 1 senden
    --> 20 ms warten
    --> Nachricht 2 senden
    --> 20ms warten
    --> Nachricht 3 senden
    --> 20ms warten

--> Callback
    --> Nachricht erfolgreich gesendet, Daten in GUI visualisieren
    --> Timeout, Daten in GUI visualisieren

von bluppdidupp (Gast)


Lesenswert?

Ich würde auch nen Thread nehmen.
Man könnte aber auch z.B. einen 20ms-Timer nehmen und was im Timer 
jeweils geschehen soll ("Nachricht 1", "Nachricht 2", ...) via 
Statemachine lösen.

von Borislav B. (boris_b)


Lesenswert?

Was gefällt dir denn an meiner Lösung mit dem Thread nicht? ;-)
Damit sollte das doch ganz einfach sein...

von nicht"Gast" (Gast)


Lesenswert?

Ich hab da mal schnell was zusammengehäckt, wie ich das machen würde.
Kommentiert habe ich absichtlich nicht.

Da lernt man ja sonst nichts dabei :)
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading;
6
using System.Threading.Tasks;
7
using System.Timers;
8
9
namespace ConsoleApplication5 {
10
    class Program {
11
        static void Main(string[] args) {
12
            SendMessages mh = new SendMessages(new List<string>() { "hallo", "welt", "das", "geht","gut"}, 1000);
13
14
            while (true)
15
                Thread.Sleep(1);
16
        }
17
    }
18
19
    class SendMessages {
20
        private List<string> messages;
21
        private List<string>.Enumerator messageIterator;
22
        private System.Timers.Timer sendTimer;
23
24
25
        public SendMessages(List<string> messagesToSend, int sendEveryMillisecound) {
26
            sendTimer = new System.Timers.Timer();
27
            sendTimer.Interval = sendEveryMillisecound;
28
            sendTimer.Elapsed += doSendMessage;
29
30
            messages = new List<string>(messagesToSend);
31
            messageIterator = messages.GetEnumerator();            
32
33
            sendTimer.Start();
34
        }
35
36
        void doSendMessage(object sender, ElapsedEventArgs e) {
37
            if (messageIterator.MoveNext()) {
38
                Console.WriteLine(messageIterator.Current);
39
            }
40
            else {
41
                Console.WriteLine("Alle Nachrichten gesendet");
42
                sendTimer.Stop();
43
            }
44
        }
45
    }
46
}

von nicht"Gast" (Gast)


Lesenswert?

hm,

wenn ich mir das so anschau....

Das ist aus dem Handgelenk geschossen. Mir fallen da noch ein paar 
Sachen auf. Das soll ja aber auch nur das Prinzip darstellen.

von Leonhard (Gast)


Lesenswert?

Guten Morgen

erstmal vielen Dank für die Hilfe. In der GUI Anwendung habe ich 
sämtliche Elemente die ich mit Daten befüllen muss. Diese Daten würden 
dann im Thread verarbeitet werden. Nun wie kann ich die Daten von dem 
Thread auf der GUI ausgeben, ohne das ein Excaption auftritt?

von Borislav B. (boris_b)


Lesenswert?

Leonhard schrieb:
> Nun wie kann ich die Daten von dem
> Thread auf der GUI ausgeben, ohne das ein Excaption auftritt?

Das Problem hast du doch bereits gelöst ;-)

Leonhard schrieb:
> Das TimerEvent synchronisiere mit der GUI Applikation anhand der Invoke
> Methode.

: Bearbeitet durch User
von Leonhard (Gast)


Lesenswert?

Ich meine nicht den Thread für die GUI sondern einen separaten 
Thread.Timer der zyklisch läuft.

von Borislav B. (boris_b)


Lesenswert?

Hä? Wie gesagt, benutze ein Invoke.

von Kaspar Hauser (Gast)


Lesenswert?

Vorher (nur mit dem Forms-Timer; es gibt auch andere), war 
Invoke/BeginInvoke unnötig, da sich dieser Timer im GUI-Thread 
zurückmeldet. Aber in deinem Extra-Thread musst du es nun verwenden, um 
auf die GUI zugreifen zu können.

von Kaspar Hauser (Gast)


Lesenswert?

BTW: Ich hoffe, dass genaues Timing (sagen wir mal, +/-30ms) nicht 
notwendig ist bei deinem Programm, denn sonst wär die Verwendung des 
Form-Timers und Sleep problematisch. Wobei Windows natürlich ohnehin 
kein Echtzeit-Betriebssystem ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.