2012-09-28 18 views
8

Ich habe eine While-Schleife in einem Windows-Dienst, der für x-mal läuft und X-Telefonanrufe nach dem Lesen von ihnen aus einer Datei. Wenn ich jetzt eine Benutzerschnittstelle herstellen möchte, die eine Option zum Stoppen der Telefonanrufe bietet, d. H. Die While-Schleife unterbrechen, noch bevor sie abgeschlossen ist. Wie soll ich es tun?Break a While-Schleife mit externen Ereignis

Nehmen wir an, ich habe eine Funktion.

DialCalls(x) 
{ 
    for(int i= 0 ; i<x ; i++) 
    { 
    // Initiate call 
    } 
} 

Es kann 2,3 DialCalls Funktionen zur gleichen Zeit in verschiedenen Threads ausgeführt sein, wie ich auch getan habe in der Anwendung Threading. Also, was ist der beste Weg, um die Schleife von einer Webseite vielleicht zu brechen.

+1

Für die Leute vorschlagen "volatile": http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx –

Antwort

6

Mit task Stornierung (neu in .net 4):

[Fact] 
public void StartAndCancel() 
{ 
    var cancellationTokenSource = new CancellationTokenSource(); 
    var token = cancellationTokenSource.Token; 
    var tasks = Enumerable.Repeat(0, 2) 
          .Select(i => Task.Run(() => Dial(token), token)) 
          .ToArray(); // start dialing on two threads 
    Thread.Sleep(200); // give the tasks time to start 
    cancellationTokenSource.Cancel(); 
    Assert.Throws<AggregateException>(() => Task.WaitAll(tasks)); 
    Assert.True(tasks.All(t => t.Status == TaskStatus.Canceled)); 
} 

public void Dial(CancellationToken token) 
{ 
    while (true) 
    { 
     token.ThrowIfCancellationRequested(); 
     Console.WriteLine("Called from thread {0}", Thread.CurrentThread.ManagedThreadId); 
     Thread.Sleep(50); 
    } 
} 

http://blogs.msdn.com/b/csharpfaq/archive/2010/07/19/parallel-programming-task-cancellation.aspx Die Aufgabe Ausnahmen schluckt, so gibt es einige Bereinigung zu, vielleicht als IDisposable? About task exceptions

+1

Dies ist eine gute Antwort (also +1), aber Sie können es verbessern, indem Sie ein paar relevante Snippets aus dem Artikel hinzufügen. –

4

Sie können eine if-Anweisung in Ihre Schleife schreiben, um den Status des externen Ereignisses abzufragen.

Zum Beispiel könnte man eine Fahne hat:

bool break_out = false;

Und in Ihrem externen Ereignisse, stellen Sie die break_out Flag auf true:

break_out = true;

Jetzt in der Schleife, Sie können haben:

DialCalls(x) 
{ 
    for(int i= 0 ; i<x ; i++) 
    { 
    // Initiate call 

    if (break_out) { 
     break; 
    } 
    } 
} 
3

Erstellen Sie ein Ereignis unterstützt Stornierung:

public event EventHandler<CancelEventArgs> Call; 

Wenn der Teilnehmer vorhanden ist, und löscht es, nicht nennen:

while (true) 
{ 
    var e = new System.ComponentModel.CancelEventArgs(); 
    if (Call != null) 
    { 
     Call(this, e); 
    } 
    if (!e.Cancel) 
    { 
     // Initiate call 
    } 
    else 
    { 
     break; 
    } 
} 
0

Durch eine variable telling verwenden, wenn zu brechen.

private bool _cancel; 

void DialCalls(...) 
{ 
    for (int i=0; i<x; i++) 
    { 
     ... 
     if (_cancel) break; 
     .... 
    } 
} 

private void SomeEventHandler(object sender, EventArgs e) 
{ 
    _cancel = true; 
} 

oder

for (int i=0; i<x && !_cancel; i++) 
0

haben eine globale Variable, die

public static volatile bool stop;  
stop=False; 

DialCalls(x) 
{ 
    for(int i= 0 ; i<x && !stop ; i++) 
    { 
    // Initiate call 
    } 
} 

On Button Click => stop =True; 
0

einen Endpunkt Implementieren auf den Dienst flüchtig ist, die eine Nachricht an, die eine globale/statische boolean schaltet (oder eine andere) Variable, und haben Sie die Schleife innerhalb DialCalls überprüfen Sie die Variable zu Beginn jeder Iteration. Es wird keine laufenden Telefonate unterbrechen, aber ich wette, dass Sie nicht wollen, dass der Dienst mitten in dem Anruf auflegt, gehen Sie einfach nicht zum nächsten weiter. Dies würde auch für alle Threads unterbrechen; Stellen Sie nur sicher, dass die Variable selbst Thread-sicher ist (z. B. volatile Schlüsselwort).

1
while (!_shouldStop) { /* work in progress */ } 

und in der Stop() Methode, die auf der gleichen Arbeiter Klasse der Boolesche Variable gesetzt werden muß wahr sein sollte.

Auch, wenn es Kellner gibt (wie AutoResetEvent), müssen sie .Set(); sein.