2016-05-20 4 views
1

BlockingCollectionと同様のforeachというセットを公開するライブラリを使用します。ここで、列挙子は次のアイテムが提供されるまで待機します。どのようにして.netでブロック列挙を終了できますか?

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

私の消費者は、次のアイテムが提供されるまでforeachを待つでしょう。準備が整うまでブロックに入りません。これは問題ありませんが、私が現在待っている場合でも、特定の条件下で列挙を意図的に停止したいと考えています。

ブロック内にbreakについて質問していません。私がブロックにいるときにループを終了するのは簡単です。列挙を別のスレッドから「取り消したい」。

+0

http://stackoverflow.com/q/23295119/11683 – GSerg

+1

の複製でもそうでなくてもかまいません。「列挙を停止する」という意味を明確にするのに役立つと思います。コードは停止しているので、次の項目をブロックして、スレッドのブロックされた列挙を別のスレッドから取り消すことについて話していると仮定できます。それとも、他に何か覚えていますか? – 31eee384

+0

ライブラリを使うと書いているので、コードの 'items'部分の実装を制御できないと思います。その場合、私はエレガントなオプションがあるとは思わない。ラグを下に引き出すことができる別のインダイレクション層を追加する以外に、最善のケースのシナリオではぎこちなく、非常に危険です。スレッドを終了すると危険です。オプションは非常に限られています。 –

答えて

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(); 
    } 
} 

はあなたのBackgroundWorkerのDoWorkメソッドは、解放される次のBlockingItemを待っている間に任意のCPUリソースを占有するつもりはありません。

変数Iが_someExternalFlagと定義されている場合は、ユーザーがキャンセルボタンをクリックするか、フォームが閉じられたときに設定されるものであれば何でも構いません。

関連する問題