2012-09-28 30 views
8

Tengo un bucle while en un servicio de Windows que se ejecuta unas x veces e inicie x llamadas telefónicas después de leerlas desde algún archivo. Ahora si quiero hacer una interfaz de usuario que ofrezca una opción para detener las llamadas telefónicas, es decir, romper el ciclo while incluso antes de que se complete. ¿Cómo lo haré?Romper un bucle while usando el evento externo

Supongamos que tengo una función.

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

No puede haber 2,3 DialCalls funciones se ejecutan al mismo tiempo en diferentes temas, como he hecho con hilo en la aplicación también. Entonces, básicamente, ¿cuál es la mejor manera de romper el ciclo de una página web?

+1

Para la gente que sugiere 'volátil': http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx –

Respuesta

6

Usando task cancelación (nuevo en .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 La tarea se traga excepciones así que hay algo de limpieza para que, tal como IDisposable? About task exceptions

+1

esta es una buena respuesta (por lo que +1), pero puede mejorarla incluyendo algunos fragmentos relevantes del artículo. –

4

Puede escribir una instrucción if dentro de su bucle, para sondear el estado del evento externo.

Por ejemplo, usted podría tener una bandera:

bool break_out = false;

Y en su evento externo, que da a la variable break_out true:

break_out = true;

Ahora en su bucle, puede tener:

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

    if (break_out) { 
     break; 
    } 
    } 
} 
3

Crear una cancelación de evento de apoyo:

public event EventHandler<CancelEventArgs> Call; 

Si existe abonado y lo cancela, no llame a:

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

Mediante el uso de un revelador variable cuando se rompa.

private bool _cancel; 

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

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

o

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

tener una variable global que es volátil

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

Implementar un punto final en el servicio que acepta un mensaje que cambia un valor lógico mundial/estática (o algún otro) variable, y tienen el bucle dentro de DialCalls para verificar dicha variable al inicio de cada iteración. No interrumpirá ninguna llamada telefónica en curso, pero apuesto a que no desea que el servicio cuelgue en el medio de la llamada, simplemente no pase al próximo. Esto también interrumpiría todos los hilos; solo asegúrese de que la variable en sí misma sea segura para subprocesos (por ejemplo, use la palabra clave volatile).

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

y en el método Stop() que debe estar en la misma clase trabajadora la variable bool se debe establecer como verdadero.

Además, si hay camareros (como AutoResetEvent) deben ser .Set();.

Cuestiones relacionadas