8 votes

Interrompre une boucle while en utilisant un événement externe

J'ai une boucle while dans un service Windows qui tourne pendant x fois et lance x appels téléphoniques après les avoir lus dans un fichier. Maintenant, si je veux créer une interface utilisateur qui donne une option pour arrêter les appels téléphoniques, c'est-à-dire interrompre la boucle avant même qu'elle ne soit terminée. Comment dois-je faire ?

Supposons que j'ai une fonction .

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

Il peut y avoir 2, 3 fonctions DialCalls fonctionnant en même temps dans des threads différents, car j'ai également fait du threading dans l'application. En fait, quelle est la meilleure façon de rompre la boucle à partir d'une page web ?

6voto

Johan Larsson Points 4405

Utilisation de tâche annulation ( nouveau dans .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 tâche avale les exceptions, il y a donc un peu de nettoyage à faire, peut-être en tant que IDisposable ? À propos des exceptions de tâches

4voto

user1032613 Points 2229

Vous pouvez écrire une instruction if à l'intérieur de votre boucle, pour interroger le statut de l'événement externe.

Par exemple, vous pourriez avoir un drapeau :

bool break_out = false;

Et dans votre événement externe, vous mettez l'indicateur break_out à true :

break_out = true;

Maintenant, dans votre boucle, vous pouvez avoir :

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

    if (break_out) {
        break;
    }
  }
}

3voto

abatishchev Points 42425

Créez un événement à l'appui de l'annulation :

public event EventHandler<CancelEventArgs> Call;

Si l'abonné existe et l'annule, n'appelez pas :

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

1voto

AgentFire Points 3818
while (!_shouldStop) { /* work in progress */ }

et dans le Stop() qui doit se trouver dans la même classe de travailleur, la variable bool doit être définie comme vraie.

Aussi, s'il y a des serveurs (comme AutoResetEvent ), ils doivent être .Set(); .

0voto

En utilisant une variable indiquant le moment de la rupture.

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++)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X