Прервать цикл while с помощью внешнего события
У меня есть цикл while в службе windows, которая работает в течение некоторого x раз и инициирует X телефонные звонки после их чтения из некоторого файла . Теперь, если я хочу сделать пользовательский интерфейс, который дает возможность остановить телефонные звонки, т. е. разорвать цикл while еще до его завершения. Как мне это сделать ?
допустим у меня есть функция .
DialCalls(x)
{
for(int i= 0 ; i<x ; i++)
{
// Initiate call
}
}
могут быть функции 2,3 DialCalls, работающие одновременно в разных потоках, как я сделал threading в применение также . Так что в основном, что лучший способ разорвать цикл с веб-страницы может быть.
7 ответов
С помощью задание отмена (новое в .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 Задача глотает исключения, поэтому есть некоторая очистка, возможно, как IDisposable? об исключениях задачи
вы можете написать if-оператор внутри вашего цикла, чтобы опросить состояние внешнего события.
например, у вас может быть флаг:
bool break_out = false;
и в вашем внешнем событии вы устанавливаете флаг break_out в true:
break_out = true;
Теперь в вашем цикле вы можете иметь:
DialCalls(x)
{
for(int i= 0 ; i<x ; i++)
{
// Initiate call
if (break_out) {
break;
}
}
}
создайте событие, поддерживающее отмену:
public event EventHandler<CancelEventArgs> Call;
Если абонент существует и отменяет его, не зови:
while (true)
{
var e = new System.ComponentModel.CancelEventArgs();
if (Call != null)
{
Call(this, e);
}
if (!e.Cancel)
{
// Initiate call
}
else
{
break;
}
}
while (!_shouldStop) { /* work in progress */ }
и Stop()
метод, который должен быть в том же рабочем классе переменная bool должна быть установлена как true.
кроме того, если есть официанты (например,AutoResetEvent
) они должны быть .Set();
.
С помощью переменной, указывающей, когда сломать.
private bool _cancel;
void DialCalls(...)
{
for (int i=0; i<x; i++)
{
...
if (_cancel) break;
....
}
}
private void SomeEventHandler(object sender, EventArgs e)
{
_cancel = true;
}
или
for (int i=0; i<x && !_cancel; i++)
имеют глобальную переменную, которая является изменчивой
public static volatile bool stop;
stop=False;
DialCalls(x)
{
for(int i= 0 ; i<x && !stop ; i++)
{
// Initiate call
}
}
On Button Click => stop =True;
реализуйте конечную точку в службе, которая принимает сообщение, которое переключает глобальную / статическую логическую (или какую-либо другую) переменную, и имеет цикл внутри DialCalls
проверить переменную в начале каждой итерации. Он не будет прерывать телефонные звонки в настоящее время, но я держу пари, что вы не хотите, чтобы служба повесила трубку в середине звонка, просто не переходите к следующему. Это также прервало бы все потоки; просто убедитесь, что сама переменная является потокобезопасной (например, используйте volatile
ключевое слово).