2016-05-20 3 views
1

Я использую библиотеку, которая предоставляет набор как foreach, аналогичный тому, как это делает BlockingCollection, где мой счетчик будет ждать, пока не появится следующий элемент.Как я могу выйти из перечисления блокировки в .net?

foreach(var item in items) 
{ 
    ... 
} 

Мой потребитель будет ждать в течение времени, пока не будет представлен следующий пункт. Он не входит в блок до готовности. Это нормально, но я бы хотел умышленно прекратить перечисление при определенных условиях, даже если я сейчас жду.

Я не спрашиваю о break внутри блока. Выход из цикла, когда я в блоке, тривиален. Я хочу «отменить» перечисление из другого потока.

+0

Возможно, это не дубликат http://stackoverflow.com/q/23295119/11683 – GSerg

+1

Я думаю, что это поможет прояснить, что вы подразумеваете под «stop перечислением». Поскольку код остановлен, блокировка на следующем элементе, я могу только предположить, что вы говорите об отмене заблокированного перечисления потока из другого потока. Или у вас есть что-то еще? – 31eee384

+0

Поскольку вы пишете, что используете библиотеку, я предполагаю, что вы не контролируете реализацию части «элементов» вашего кода. В этом случае я не думаю, что есть элегантный вариант. Помимо добавления другого слоя косвенности, вы можете вытащить ковер под ним, который будет неуклюжим в лучшем случае - или совершенно опасным, если вы начнете завершать потоки - ваши варианты очень ограничены. –

ответ

1

Это некрасиво, но вы можете обернуть это внутри BackgroundWorker или другой технологией нитей.

Я не знаю, что ваш BlockingCollection есть, но я буду считать для кода ниже, что она состоит из BlockingItem коллекции.

private bool _someExternalFlag; 

private void Test(BlockingCollection items) 
{ 
    _someExternalFlag = false; 
    using (var worker = new BackgroundWorker()) 
    { 
     worker.WorkerReportsProgress = true; 
     worker.WorkerSupportsCancellation = true; 
     worker.DoWork += delegate 
     { 
      var index = 0; 
      foreach (var item in items) 
      { 
       if (worker.CancellationPending) 
       { 
        break; 
       } 
       index++; 
       // ... process your item here or by passing it to the main thread 
       worker.ReportProgress(index, item); 
      } 
     }; 
     worker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e) 
     { 
      if (_someExternalFlag) 
      { 
       worker.CancelAsync(); 
      } 
      else 
      { 
       var item = e.UserState as BlockingItem; 
       // use item if you need it 
      } 
     }; 
     worker.RunWorkerAsync(); 
    } 
} 

метод DoWork Ваш BackgroundWorker является не собирается принимать все ресурсы процессора, пока он ждет следующего BlockingItem должен быть освобожден.

Переменная I, определяемая _someExternalFlag, может быть любым, что установлено, когда пользователь нажимает кнопку «Отмена» или задает, когда форма закрыта.