C# Thread.Sleep Problem

Gotenks666

Ensign
Registriert
Mai 2009
Beiträge
165
Hallo Leute,
ich brauche mal wieder eure Hilfe.
Diesesmal geht es um das warten bis etwas gestartet wird...

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
       public Form1()
        {
            InitializeComponent();
        }

       private void button1_Click(object sender, EventArgs e)
       {
           if (checkBox1.Checked)
           {
               richTextBox1.Text = richTextBox1.Text + "Server wird gestartet\n";
               Thread.Sleep(5000);
               Process.Start("C:Server1exe");
               richTextBox1.Text = richTextBox1.Text + "Account Server wurde gestartet\n";

           }
            if (checkBox2.Checked)
            {
                richTextBox1.Text = richTextBox1.Text + "Server wird gestartet\n";
                Thread.Sleep(3000);
                Process.Start("CServer2.exe");
                richTextBox1.Text = richTextBox1.Text + "Certifier Server wurde gestartet\n";
            }

Das Problem mit dem Thread.Sleep ist das wen ich das Programm starte er erstmal 5 Sekunden wartet und dan aber beide Server auf einmal startet.

Ich möchte aber das das Programm die Server immer in einem Abstand von 3 Sekunden startet... könnt ihr mir bitte helfen?
 
Ich würde mal jetzt erwarten das weder der eine noch der andere Server startet:

Code:
Process.Start("C:Server1exe");
// bzw.
Process.Start("CServer2.exe");

Sind beide Pfade wirklich richtig?

Desweiteren: soll der 2. Server 3 sek. später starten, nach dem der 1. Server gestartet ist oder gestartet wird?

Soweit ich das sehe, wird 3 Sek. gewartet, d.h. aber nicht das da der 1. Server schon vollständig läuft. Process.Start wäre doch eigentlich asynchron, wenn ich mich jetzt nicht arg täusche.

EDIT:
Eventuell könntest du mal das hier zum starten probieren:
Code:
System.Diagnostics.Process server1 = System.Diagnostics.Process.Start("C:\Server1.exe");
server1.WaitForInputIdle();

Damit das aber funktioniert, muss der Prozess in diesem Fall Server1.exe eine Meldungsschleife haben. Ansonsten wird nicht gewartet.

Alternativ bietet sich noch folgendes an, wenn der Server keine Meldungsschleife besitzt:

Code:
System.Diagnostics.Process server1 = System.Diagnostics.Process.Start("C:\Server1.exe");
while(server1.Modules.Count == 0)
  System.Threading.Thread.Sleep(100);

Es wird dann solange gewartet bis die einzelnen Module des Prozesses (EXE + DLLs) geladen sind. Damit kann man davon ausgehen, das der Prozess auch gestartet ist.
 
Zuletzt bearbeitet: (Codebeispiele fürs Warten ergänzt)
Ja aber er wartet jetzt zB 3Sekunden dan starten sich beide Server gleichzeitig.

Ich möchte aber das sich die Server in einem Abstand von 3 Sekunden starten.

z.B

Server 1 -> Start
3sek warten
Server 2 -> Start
3sek warten
Server 3 -> Start

Code:
 private void button1_Click(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                richTextBox1.Text = richTextBox1.Text + "Server wird gestartet\n";
                System.Diagnostics.Process server1 = System.Diagnostics.Process.Start("C:Server1.exe");
                while(server1.Modules.Count == 0)
                System.Threading.Thread.Sleep(3000);
                richTextBox1.Text = richTextBox1.Text + "Account Server wurde gestartet\n";

            }
            if (checkBox2.Checked)
            {
                richTextBox1.Text = richTextBox1.Text + "Server wird gestartet\n";
                System.Diagnostics.Process server2 = System.Diagnostics.Process.Start("C:Server2.exe");
                while(server2.Modules.Count == 0)
                System.Threading.Thread.Sleep(3000);
                richTextBox1.Text = richTextBox1.Text + "Certifier Server wurde gestartet\n";
            }

Aber er startet trozdem beide Server gleichzeitig wen ich auf den Button Klicke
 
bin noch am Nachdenken. BTW: Das Laden der Module ist bei mir recht schnell sodaß die 3sek. Warten innerhalb der Schleife nicht ausgeführt werden. Ich werde mal ein bißchen "rumspielen" vielleicht ergibt sich was, vielleicht auch nicht. Übrigens sehe ich schon wieder das die Pfade nicht gut sind "C:Server1.exe" sieht genauso komisch aus wie "C:Server2.exe".
 
wenn er beide Server startet, dann auch, weil beide CheckBoxen gechecked sind...

Weiter, möchte ich noch an der Schreibweise der "While-schleife" nörgeln:
Für gewöhnlich schreibt man das lieber so:
Code:
while(Boolean)
{ 
   Anweisungen;
}

Wobei in deinem Fall vielleicht eine do-while Schleife besser ist, weil so auf jedenfall mindestens einmal die Anweisung ausgeführt wird, in deinem Fall das Warten:

Code:
do 
{ 
   Anweisungen;
}
while(Boolean);

In deinem ersten Versuch hat er zuerst 5sec gewartet, weil die Anweisung zu warten auch vor dem starten des Threads stand...
 
Zuletzt bearbeitet:
Erdmännchen schrieb:
wenn er beide Server startet, dann auch, weil beide CheckBoxen gechecked sind...

Was ja auch gewünscht sein wäre, wenn ich das Vorhaben vom TE richtig verstanden habe.

Erdmännchen schrieb:
Weiter, möchte ich noch an der Schreibweise der "While-schleife" nörgeln:
Für gewöhnlich schreibt man das lieber so:
Code:
while(Boolean)
{ 
   Anweisungen;
}

Nörgeln kann jeder. Jedoch wenn es hier nur um eine einzige Anweisung geht, die in der Schleife ausgeführt werden soll, warum soll man dann das ganze nochmal in den geschweiften Klammern verpacken?

EDIT: Habe jetzt mal eine neue Variante "gebaut":

Code:
private void button1_Click(object sender, EventArgs e)
{
  if (checkBox1.Checked)
    StartServer("C:\\Server1.exe", 5, 3, "Account Server wurde gestartet");
  if (checkBox2.Checked)
    StartServer("C:\\Server2.exe", 0, 0, "Certifier Server wurde gestartet");
}

private void StartServer(string commandServer, int waitBeforeInSeconds, int waitAfterInSeconds, string messageAfterStart)
{
   System.Threading.Thread.Sleep(waitBeforeInSeconds * 1000);
   richTextBox1.Text = richTextBox1.Text + "Server wird gestartet\n";
   System.Diagnostics.Process.Start(commandServer);
   richTextBox1.Text = richTextBox1.Text + messageAfterStart + "\n";
   System.Threading.Thread.Sleep(waitAfterInSeconds * 1000);
}

Anmerkung: Ich denke die Server haben schon die richtige Zeit in deinem 1. Code gewartet, jedoch kam die Anzeige in der richTextBox1, was gerade gemacht wird/wurde, unmittelbar hintereinander, da diese noch vor bzw. erst hinter dem Warten standen. Hast du mal deinen Code im Debugger Schritt-für-Schritt geprüft?
 
Zuletzt bearbeitet:
Es gehört nunmal zum guten Stil, und somit ist es lesbarer für Fremdleser...

Dein letzter Ansatz schaut gut aus, würde aber die Sleep-Anweisung vor der zweiten Ausgabe machen, weil das wohl logischer ist, dass nach der Nachricht "Server wird gestartet" ein wenig Zeit vergeht, bis die Nachricht "XXXXX Server wurde gestartet" ausgegeben wird.

Nochmal zu meiner Nörgel Intention:
Sauberer Code muss nicht nur dir, sondern auch fremden Augen logisch erscheinen und was viel wichtiger ist schnell aufgefasst werden und verstanden werden.
Dazu gehört eben, dass man Schleifen mit nur einer Zeile Code samt Signatur in nur eine Zeile schreibt oder eben einen Block drum macht. Aber wenn du es so schreibst wie oben, muss der Leser erst die erste Zeile auffassen, dann die zweite und überlegt dann, moment, das was folgt, gehört das auch noch zur Schleife und es wurde kein Block gesetzt oder wie jetzt?
Vor allem Nutzer, die verschiedene Programmiersprachen lesen können, werden es dir danken ;)

Wenn die Thematik dich mehr interessiert, empfehle ich dir sehr das Buch "Clean Code" von Robert C. Martin (gibts auch in einer brauchbaren deutschen Fassung).
Keine Angst, ich dachte auch, warum, wenn meine IDE das versteht, dass ich das in zwei Zeilen schreib ohne Block, warum dann nicht die Klammern sparen?
Aber das ist einfach nicht gesund ;)
Irgendwann wirst du es verstehen, wenn ich dich jetzt noch nicht überzeugt hab ...

Und warum nörgel ich da schon in Kleinigkeiten, um die es gar nicht geht?
-> Es geht ums Prinzip, wenn wieder ein neuer Programmiere das verstanden hat, dann schaut die dreckige Code Welt wieder ein wenig sauberer aus :D
 
Dein letzter Ansatz schaut gut aus, würde aber die Sleep-Anweisung vor der zweiten Ausgabe machen, weil das wohl logischer ist, dass nach der Nachricht "Server wird gestartet" ein wenig Zeit vergeht, bis die Nachricht "XXXXX Server wurde gestartet" ausgegeben wird.

Ich könnte da schon fast zustimmen, aber leider ist das nur eine einseitige - wenn auch gleichberechtigte - Ansicht aus den Augen des Anwenders. Derjenige der nun diese Funktion in seinem eigenen Programmcode verwendet, sieht es nach meiner Ansicht vielleicht etwas anders, wenn er nur die Signatur der Methode kennt.

waitBeforeInSeconds - Wartezeit vor der Aktion
waitAfterInSeconds - Wartezeit nach der Aktion

Mit der Positionierung der Sleeps innerhalb der Methode erreiche ich eine weitestgehend exakte Wiedergabe dessen, was ich dem Verwender der Methode durch die Signatur verspreche. Dein Lösungsansatz würde jedoch den Zusammenhang der Definition der Methode und deren Implementierung aufweichen und somit nicht wirklich schlüssig sein. Macht sich in größeren Projekten mit mehreren Entwicklern - die nicht die Zeit haben - den Code zu reviewen äußerst schlecht. ;)

Zum Thema "Clean Code":
Wann immer Idealisten ihre Ideale dem Rest der Bevölkerung aufzwangen, lösten Sie dadurch die größten Katastrophen der Menscheitsgeschichte aus. Aber mal Spaß bei Seite. Es ist gut einen gewissen Standard zu etablieren. Da rennst du bei mir offene Türen ein. Es gibt viele sehr unterschiedliche Standards, die alle ihre Vor- und Nachteile haben, es gibt aber nicht DEN Standard. Jetzt und hier verfahre ich lieber nach dem Bedarfsprinzip, wenn ich den Bedarf habe, dann mache ich das, wenn nicht bleibt es so wie es ist. Gegenwärtig sehe ich für mich hier im Forum nicht den Bedarf nach einem Standard zu programmieren um irgendwen das Ganze mundgerecht zu präsentieren. Es ist meine Freizeit, mein privates Vergnügen, dass ich gern auf Fragen antworte, neue Fragen stelle, einen kleinen Denkanstoß liefere oder vielleicht auch mal ein bißchen Code spendiere. Ich verdiene kein Geld damit, es kostet mich Geld: sei es Strom, Hardware, Software oder die Zeit. Also bitte betrachte das, was ich hier hin und wieder poste als das, was es ist - nur das Freizeitwerk eines mehr oder weniger aktiven Forummitglieds! Diese Codes sind weder optimiert, noch in irgend eine Weise an irgendwelche Standards gebunden. Kurzum - für den Produktionseinsatz nicht geeignet und nur ein Proof-Of-Concept! Einem geschenkten Barsch schaut man nicht in den Arsch. :D

Und nun bin ich wieder mal völlig am eigentlichen Thema vorbei geschossen...

Noch eine Frage an den TE um das Thema nicht ganz außer Acht zu lassen.

@Gotenks: Wie schaut es aus, zeigt sich nun, dass die Server erst mit 3sek Abstand gestartet werden oder nicht?


Happy coding...
Rossibaer
 
Hallöchen ich habe auch ein Problem mit System.Threading.Thread.Sleep und zwar habe ich folgendes geschrieben.

textbox1.text=("hier steht irgend ein text");
System.Threading.Thread.Sleep("2000");

ich wollte das er erst das Textfeld ausfüllt und dann wartet aber er macht es komischerweise genau andersherum er wartet 2 Sekunden und füllt dann das Feld aus weis einer wie ich das beheben kann ?
 
Du musst dazwischen eine Neuzeichnung der Textbox erzwingen.
 
@DragonTHB: Der Titel heißt zwar "Thread.Sleep Problem" hat aber rein gar nichts mit deinem Problem zu tun. Ein neuer Thread wäre sinvoller.

Mit dem Sleep blockierst du den Dispatcher-Thread, der für das Zeichnen und Interaktion mit der GUI verantwortlich ist.
Entweder du machst es "quick & dirty" wie KamehamehaX10 schreibt, oder richtig in einem separaten Thread. Je nach Anwendungsfall bietet dir C# mehrere Möglichkeiten, das umzusetzen.
 

Ähnliche Themen

Zurück
Oben