Forum: PC-Programmierung C# Endlosschleifen mit Button unterbrechen


von Rene P. (rene1989)


Lesenswert?

Ich habe 2 Buttons
Mit dem 1. will ich die Endlosschleife starten und mit dem anderen 
wieder beenden.
Mein Problem ist das während der Endlosschleife die Buttons nicht mehr 
betätigen kann weil er in der Schleife "hängen" bleibt.
1
//Start
2
private void start_Click(object sender, EventArgs e)
3
{
4
...
5
  while() Endlosschleife
6
}
7
8
//Stop
9
private void stop_Click(object sender, EventArgs e)
10
{
11
  ...Endlosschleife unterbrechen
12
}

danke schon im Voraus für eure Hilfe

mfg Rene

von Mars (Gast)


Lesenswert?

Du hast ja auch nur einen Thread. Wenn dieser in der Schleife hängt, 
kannst du logischerweise den zweiten Button nicht mehr drücken.
=> Endlosschleife in einen eigenen Thread auslagern. Die 
BackgroundWorker Klasse nimmt dir einiges an Arbeit ab und die Beispiel 
in der MSDN sind auch sehr gut.

Lg

von Rene P. (rene1989)


Lesenswert?

hmm mit C# sharp hab ich mich noch nicht so gut befasst

Wie kann man einen 2.Tread machen?

danke mfg

von Mars (Gast)


Lesenswert?

Dann wird es aber Zeit!

Nimm die BackgroundWorker Klasse, diese nimmt dir bereits die 
Threadsynchronisierung für GUI Zugriffe ab.

von Sebastian (Gast)


Lesenswert?

Mit Application.DoEvents() innerhalb der Schleife gehts auch ohne 
Multithreading.

von Severino R. (severino)


Lesenswert?

Sebastian wrote:
> Mit Application.DoEvents() innerhalb der Schleife gehts auch ohne
> Multithreading.

Ja, und in stop_Click() Flag setzen und in der Endlosschleife abfragen.

Flag initialisieren nicht vergessen!

von Chris .. (dechavue)


Lesenswert?

Hi,

Ich möchte noch anmerken, dass die Methode mit Application.DoEvents() 
eher die Quick and VERY DIRTY - Methode ist.

Besser ist es, das Ganze mit Threads zu machen, was ja dank 
Backgroundworker überhaupt keine Hexerei ist.

Anbei ein Kleines Beispiel, wie das Ganze mit dem BW funktioniert (inkl. 
Parameterübergabe, Ergebnisrückgabe und Fortschrittsmeldung 
zwischendurch)
1
        private BackgroundWorker m_BackgroundWorker = new BackgroundWorker();
2
3
        public Form1() {
4
            InitializeComponent();
5
6
            m_BackgroundWorker.DoWork += new DoWorkEventHandler(m_BackgroundWorker_DoWork);
7
            m_BackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(m_BackgroundWorker_ProgressChanged);
8
            m_BackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_BackgroundWorker_RunWorkerCompleted);
9
            m_BackgroundWorker.WorkerReportsProgress = true;
10
        }
11
12
        private void m_BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
13
            // GUI - Thread
14
15
            //e.Cancelled ... Indicates if the Operation was cancelled
16
            //e.Error     ... An Exception which was thrown inside the Async Operation
17
            //e.Result    ... A Result Object
18
        }
19
20
        private void m_BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
21
            // GUI - Thread
22
            
23
            //z.B.:
24
            //m_Progressbar.Value = e.ProgressPercentage
25
            //Do Something with e.UserState
26
        }
27
28
        private void m_BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
29
            //Worker - Thread
30
            
31
            //Do Something with e.Argument
32
            int i = 0;
33
            do {
34
                m_BackgroundWorker.ReportProgress(i++ % 100/*, Optional: any Object*/);
35
            } while (!e.Cancel);
36
            //e.Result = Any result Object
37
        }
38
39
        private void button1_Click(object sender, EventArgs e) {
40
            m_BackgroundWorker.RunWorkerAsync(/*Optional: Any Object*/);
41
        }
42
43
        private void button2_Click(object sender, EventArgs e) {
44
            m_BackgroundWorker.CancelAsync();
45
        }

greets

PS: Ich appeliere nochmal an dich BITTE nimm nicht 
Application.DoEvents(), du handelst dir damit früher oder später nur 
Probleme ein.

von Rene P. (rene1989)


Lesenswert?

vielen dank für deine Hilfe
ich habe jetzt eine weile experimentiert aber verstehe noch immer nicht 
wie der Backgroundworker genau funktioniert.

wie würde ich eine Endlosschleife machen, die in einem Label immer die 
Zahl um 1 erhöht. Mit einem Button wird die Schleife gestartet und mit 
einem anderen wieder abgebrochen.

von Crimson (Gast)


Lesenswert?

Hi,

verwende für so etwas doch einfach einen Timer mit einem Click auf den 
Button 1 wird der Timer gestartet und mit einem Click auf den Button 2 
wieder angehalten. In dem Timer kann man dan auch noch den zeitlichen 
Abstand einstellen.
Z.B.:
1
public partial class Form1 : Form
2
    {
3
        public Timer timer1;
4
        public long laufvar;
5
        public Form1()
6
        {
7
            InitializeComponent();
8
            
9
            timer1 = new Timer();
10
            timer1.Interval = 1000; // in Millisekunden
11
            timer1.Tick +=new EventHandler(timer1_Tick);
12
            laufvar = new long();
13
            laufvar = 0;
14
        }
15
16
        void  timer1_Tick(object sender, EventArgs e)
17
        {
18
            label1.Text = laufvar.ToString();
19
            laufvar++;
20
        }
21
22
        private void button1_Click(object sender, EventArgs e)
23
        {
24
            timer1.Start();
25
        }
26
27
        
28
29
        private void button2_Click(object sender, EventArgs e)
30
        {
31
            timer1.Stop();
32
        }
33
34
        
35
    }

Das einzige was da noch fehlt sind zwei Buttons sowie ein label auf dem 
Form1 und du hast eine Sekunden Stopuhr.
Aber für so etwas würde ich nicht mit Threads anfangen.

von Marco (Gast)


Lesenswert?

Hallo..

Jetzt habe ich noch mal eine ergänzende Frage zum BW.

Ich muss hin und wieder eine mathematische Operation ausführen, die ich 
in einem separaten Thread laufen lasse. Dieser Thread arbeitet ständig 
und wird nur durch ein Thread.Sleep für einige Zeit zum stoppen 
gebracht.

Thread worker = new Thread(Work);
worker.Start();
1
private void Work()     
2
{
3
 while (true)
4
 {
5
    try 
6
    {
7
      //...Berechne...
8
      Thread.Sleep(1000);
9
    }   
10
    catch(Exception) {}
11
  }
12
}

Natürlich ist diese Art der Programmierung "very very dirty", allerdings 
kann ich einen BW, denn ich einmalig initialisiert habe, auch mehrfach 
starten und stoppen?

von Raphael (Gast)


Lesenswert?

1
bool beende;
2
Thread t;
3
private void button1_Click()
4
{
5
   beende = false;
6
   t = New Thread(new ThreadStart(run));
7
   t.Start();
8
}
9
10
void run()
11
{
12
  while(!beende)
13
  { /*mache irgendwas*/ }
14
}
15
16
private void  button2_click()
17
{
18
    beende = true;
19
}
So würde es mal aussehen, wenn man nicht den BW nehmen will.

von Klugscheisser (Gast)


Lesenswert?

Dann ist das doch aber keine ENDLOSschleife mehr wenn die unterbrochen 
wird!

von Rolf Magnus (Gast)


Lesenswert?

Es dürfte auch nicht allzuviele echte Endlosschleifen geben. Irgendwie 
werden sie doch alle früher oder später unterbrochen.

von Sven P. (Gast)


Lesenswert?

Gilt das mit VOLATILE eigentlich für C# nicht mehr?

von Andreas F. (andilein)


Lesenswert?

kann mir jemand sagen wie ich zu meinem label komme?
also ich sollte den "label1.Text" ändern!

..es geht um diesen beitrag hier:


Autor: Crimson (Gast)
Datum: 24.02.2009 17:04

von Karl H. (kbuchegg)


Lesenswert?

Andreas F. schrieb:
> kann mir jemand sagen wie ich zu meinem label komme?
> also ich sollte den "label1.Text" ändern!

Zieh einfach ein Label-Control aus deinem Controlvorrat auf die Form.

(PS: Sag niemandem, dass du C# programmierst)

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.