title: How To Cancel Any Current Parallel.ForEach And Start Fresh
body: <p>Functionally have a long list of words bound to a ListView.  Use a TextBox for  chars to filter the list of words.  </p>
  
  <p>With any new char need to cancel any processing background filter.  Then wait 1 second (DispatcherTimer) to start a fresh background parallel filter.  </p>
  
  <p>Have this working using BackGroundWorker but cannot translate the cancel-any-processing part to Parallel.
  Basically need "if (backgroundWorkerFTSfilter.IsBusy) backgroundWorkerFTSfilter.CancelAsync();" in Parallel.<br>
  If I am going about this wrong please let me know.</p>
  
  <pre><code>private List&lt;FTSword&gt; fTSwordsFiltered = new List&lt;FTSword&gt;();
  CancellationTokenSource ftsCts = new CancellationTokenSource();
  ParallelOptions ftspo = new ParallelOptions();
  // in ctor ftspo.CancellationToken = ftsCts.Token;
  
  public List&lt;FTSword&gt; FTSwordsFiltered  // ListView bound to
  {
      get { return fTSwordsFiltered; }
      set
      {
          if (fTSwordsFiltered == value) return;
          fTSwordsFiltered = value;
          NotifyPropertyChanged("FTSwordsFiltered");
      }
  }
  public string FTSwordFilter            // TextBox bound to
  {
      get { return fTSwordFilter; }
      set
      {
          if (value == fTSwordFilter) return;
  
          fTSwordFilter = value;
          NotifyPropertyChanged("FTSwordFilter");
  
          // cancel any filter currently processing
          ftsCts.Cancel();   // fts filter              
          // with BackgroundWorker this was able to cancel               
          // if (backgroundWorkerFTSfilter.IsBusy) backgroundWorkerFTSfilter.CancelAsync();
  
          dispatcherTimerFTSfilter.Stop();
          // wait 1 second and apply filter in background
          dispatcherTimerFTSfilter.Start();
      }
  }
  private void dispatcherTimerFTSfilter_Tick(object sender, EventArgs e)
  {
      dispatcherTimerFTSfilter.Stop();
      List&lt;FTSword&gt; ftsWords = new List&lt;FTSword&gt;();
      //ftsCts = new CancellationTokenSource();  with these two it never cancels
      //ftspo.CancellationToken = ftsCts.Token;
      if (!(string.IsNullOrEmpty(FTSwordFilter)))
      {
          Task.Factory.StartNew(() =&gt;
          {
  
              try
              {
                  Parallel.ForEach(FTSwords, ftspo, ftsw =&gt;
                  {
                      if (ftsw.WordStem.StartsWith(FTSwordFilter))
                      {
                          ftsWords.Add(ftsw);
                      }
                      ftspo.CancellationToken.ThrowIfCancellationRequested();
                  });
                  Thread.Sleep(1000);   // so the next key stoke has time
                  FTSwordsFiltered = (List&lt;FTSword&gt;)ftsWords;
              }
              catch (OperationCanceledException ei)
              {
                  // problem is that it is always cancelled from the cancel request before DispatchTimer
                  Debug.WriteLine(ei.Message);
              }
              Debug.WriteLine(ftsWords.Count.ToString() + "parallel ");
          });           
      }
  }
  </code></pre>
  
  <p>The answer from Irman led me to this</p>
  
  <pre><code>    if (!(string.IsNullOrEmpty(FTSwordFilter)))
      {
          string startWorkFilter = FTSwordFilter;
          Task.Factory.StartNew(() =&gt;
          {
              try
              {
                  fTSwordsFilteredCancel = false;
                  Parallel.ForEach(FTSwords, ftspo, (ftsw, loopstate) =&gt;
                  {
                      if (ftsw.WordStem.StartsWith(startWorkFilter))
                      {
                          ftsWords.Add(ftsw);
                      }
                      // Thread.Sleep(1);
                      if (fTSwordsFilteredCancel)
                      {
                          loopstate.Break();
                      }
                  });
                  Debug.WriteLine("fTSwordsFilteredCancel " + fTSwordsFilteredCancel.ToString());
                  FTSwordsFiltered = (List&lt;FTSword&gt;)ftsWords;
                  Debug.WriteLine(ftsWords.Count.ToString() + " parallel " + startWorkFilter);                       
              }
              catch (OperationCanceledException ei)
              {
                  Debug.WriteLine(ei.Message);
              }
          });
      }
  </code></pre>
  
  <p>Very grateful for the answer I and will use this for some longer running tasks or longer list but got such great performance I moved this to the get (still with a 1 second delay).    Results in a smaller memory footprint.   Against 800,000 it runs in less than 1/10 second. </p>
  
  <pre><code>public IEnumerable&lt;FTSword&gt; FTSwordsFiltered
  {
      get 
      { 
          if(string.IsNullOrEmpty(FTSwordFilter) || FTSwordFilter == "*") return FTSwords; 
          return FTSwords.AsParallel().Where(ftsWrd =&gt; ftsWrd.WordStem.StartsWith(FTSwordFilter));
      }
  </code></pre>