2009-08-27 6 views
1

Есть ли способ остановить запущенный цикл внутри другого метода или динамически вставить оператор break в C#?Остановить цикл внутри метода в C#

Благодаря

Edit: я хочу, чтобы иметь возможность динамически перехватывать метод и вставить паузу, чтобы остановить цикл, когда событие сработало в другом function.I есть несколько экземпляров класса, и я хочу, чтобы остановить цикл в каждом случае, когда требуется, и управлять всеми экземплярами. Рассмотрим несколько примеров, чтобы быть в общем списке

Пример:

List<myclass> objlist=new List<myclass>(); 

foreach(myclass obj in objlist) 
{ 
obj.loopingfunction().BreakLoop //or something like this (assuming that the loopingfunction is already called) 
} 

мне это нужно, потому что я хочу, чтобы разорвать цикл, когда пользователь магазинах некоторые огромное количество data.When пользователь импортирует данные, я получить событие. Но я не могу продолжать проверять базу данных из нескольких экземпляров, так как она закручивает sqlserver.

Это приложение ASP.Net.

ответ

7

Если все это работает в одном потоке, это не имело бы никакого смысла. Если цикл запущен, то ничего не запускается одновременно. Если вы используете цикл в другом потоке и управляющий метод в другом потоке, вы можете полностью прекратить поток цикла или проверить флаг внутри цикла, чтобы решить, следует ли вам разрывать и правильно установить флаг в методе управления ,

Update: сделать что функция возвращает логическое значение, указывающее, следует ли вы перерыв и использовать его в качестве «if» заявление:

if (myFunctionShouldBreakLoop()) break; 
+0

В случае с одним потоком его код может быть делегатом, вызванным внутри цикла, и в этом случае я могу увидеть сценарии, в которых он хотел бы прервать цикл. Не то, чтобы это облегчило ... –

+0

Franci: В этом случае это не «динамически» ломается. В основном это просто опрос другого метода и использует его возвращаемое значение, чтобы увидеть, должно ли оно сломаться или нет. –

+0

Проблема в том, что я не могу проверить myFunctionShouldBreakLoop(), поскольку .... в моем случае эта функция должна получить доступ к базе данных и проверить, сохранил ли пользователь данные. – Josh

2

Имейте условие в запертом состоянии.

private Boolean BreakCondition 
{ 
    get { lock(_LockObject) { return _BreakCondition; } } 
    set { lock(_LockObject) { _BreakCondition = value; } } 
} 
private Boolean _BreakCondition = false; 
private Object _LockObject = new Object(); 


if (this.BreakCondition) 
{ 
    break; 
} 
+0

Вы можете заблокировать, что 'if', а также. – Kobi

+0

Что значит? – ChaosPandion

+0

Это очень бесполезно, доступ к логическому значению является атомарным. –

1

Я думаю, что вы можете использовать пометку

bool stop = false; 

for(int i=0;i<num;i++) 
{ 
if(stop) break; 
} 
3

Другим вариантом было бы поднять CancelEventArgs при каждой итерации цикла. Возможно, не самый эффективный, но другой вариант, тем не менее:

private void SomeMethod() 
    { 
     for (int i = 0; i <= 100000; i++) 
     { 
      Console.WriteLine(i); 
      if (LoopIncrement != null) 
      { 
       CancelEventArgs args = new CancelEventArgs(); 
       LoopIncrement(null, args); 
       if (args.Cancel) 
       { 
        break; 
       } 
      } 
     } 

А потом в другом месте:

myObj.LoopIncrement += MyHandler; 

private void MyHandler(object sender, CancelEventArgs e) 
{ 
    if(someCondition) 
    { 
     e.Cancel = true; 
    } 
} 

Таким образом, вы можете несколько контролировать петлю снаружи ....

1

Короткий ответ нет. Если вы не контролируете код, вы не можете заставить цикл завершить работу.

Если вы контролируете код, вы можете создать какое-то сотрудничество, но это звучит беспорядочно. Может быть, вы можете уточнить, почему?

2

Как насчет использования итераторов и получения магии для решения проблемы.

Вот статья на бесконечных списках, которые могут быть полезны

http://www.codethinked.com/post/2009/02/04/Infinite-Lists-With-C-Yield.aspx

class Program 
    { 
     static void Main(string[] args) 
     { 
      Predicate<int> when = i => i > 100 && Console.ReadKey().KeyChar.ToString() == "0"; 

      foreach(var i in Numbers().BreakOn(when)) 
      { 
       Console.WriteLine(i); 
      } 

      Console.ReadLine(); 
     } 

     private static IEnumerable<int> Numbers() 
     { 
      var i = 0; 
      while(true) 
      { 
       yield return i++; 
      } 
     } 


    } 

    public static class Util 
    { 
     public static IEnumerable<int> BreakOn(this IEnumerable<int> sequence, Predicate<int> when) 
     { 
      foreach(int i in sequence) 
      { 
       if(when(i)) 
       { 
        yield break; 
       } 
       yield return i; 
      } 
     } 
} 
+0

Вау, это фантастическая идея. доходность может дать мне нечто похожее синтаксис. Мне нравится, как парень объясняет это. Просто превосходная ... часть, которую он называет академической. Но тогда ... практически, это будет цикл для проверки и установки логического значения. Спасибо за эту идею и статью – Josh

+0

Мне нравится статья и ваша идея. Но, в конечном счете, мне нужен способ разбить цикл с помощью внешняя функция, даже если я правильно использую доходность и внешние методы? Как я разбиваю его посередине? – Josh

+0

Это было бы похоже на Take (100). Бесконечный цикл прерывается, когда счет достигает 100. Таким образом, вам нужно определить метод расширения для IEnumerable и использовать «break break»; если ваш нарушение состояние соответствует. Поскольку вы можете объединить все итераторы вместе, и каждый элемент обрабатывается как элементы на конвейерной ленте, петля заканчивается, когда ваш код достигает предела выхода. – chandmk

Смежные вопросы