Funkcjonalnie mają długą listę słów związanych z ListView. Użyj pola TextBox dla znaków, aby przefiltrować listę słów.Jak anulować dowolny bieżący Parallel.ForEach i rozpocząć świeże
Przy każdym nowym char trzeba anulować filtr przetwarzania w tle. Następnie odczekaj 1 sekundę (DispatcherTimer), aby uruchomić świeży filtr równoległy tła.
Wykonaj tę operację za pomocą BackGroundWorker, ale nie możesz przetłumaczyć części cancel-any-processing na Parallel. Zasadniczo potrzebujesz "if (backgroundWorkerFTSfilter.IsBusy) backgroundWorkerFTSfilter.CancelAsync();" równolegle.
Jeśli mam zamiar rozwiązać ten problem, proszę dać mi znać.
private List<FTSword> fTSwordsFiltered = new List<FTSword>();
CancellationTokenSource ftsCts = new CancellationTokenSource();
ParallelOptions ftspo = new ParallelOptions();
// in ctor ftspo.CancellationToken = ftsCts.Token;
public List<FTSword> 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<FTSword> ftsWords = new List<FTSword>();
//ftsCts = new CancellationTokenSource(); with these two it never cancels
//ftspo.CancellationToken = ftsCts.Token;
if (!(string.IsNullOrEmpty(FTSwordFilter)))
{
Task.Factory.StartNew(() =>
{
try
{
Parallel.ForEach(FTSwords, ftspo, ftsw =>
{
if (ftsw.WordStem.StartsWith(FTSwordFilter))
{
ftsWords.Add(ftsw);
}
ftspo.CancellationToken.ThrowIfCancellationRequested();
});
Thread.Sleep(1000); // so the next key stoke has time
FTSwordsFiltered = (List<FTSword>)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 ");
});
}
}
Odpowiedź z Irman doprowadziły mnie do tego
if (!(string.IsNullOrEmpty(FTSwordFilter)))
{
string startWorkFilter = FTSwordFilter;
Task.Factory.StartNew(() =>
{
try
{
fTSwordsFilteredCancel = false;
Parallel.ForEach(FTSwords, ftspo, (ftsw, loopstate) =>
{
if (ftsw.WordStem.StartsWith(startWorkFilter))
{
ftsWords.Add(ftsw);
}
// Thread.Sleep(1);
if (fTSwordsFilteredCancel)
{
loopstate.Break();
}
});
Debug.WriteLine("fTSwordsFilteredCancel " + fTSwordsFilteredCancel.ToString());
FTSwordsFiltered = (List<FTSword>)ftsWords;
Debug.WriteLine(ftsWords.Count.ToString() + " parallel " + startWorkFilter);
}
catch (OperationCanceledException ei)
{
Debug.WriteLine(ei.Message);
}
});
}
bardzo wdzięczny za odpowiedź I i wykorzysta to dla niektórych już uruchomionych zadań lub dłuższej liście, ale mam taką wielką wydajność przeniosłem to do get (wciąż z 1 sekundowym opóźnieniem). Wynikiem jest mniejszy ślad pamięci. Przeciw 800,000 działa w mniej niż 1/10 sekundy.
public IEnumerable<FTSword> FTSwordsFiltered
{
get
{
if(string.IsNullOrEmpty(FTSwordFilter) || FTSwordFilter == "*") return FTSwords;
return FTSwords.AsParallel().Where(ftsWrd => ftsWrd.WordStem.StartsWith(FTSwordFilter));
}
Proszę sprawdzić, co moim zdaniem jest prawidłowe użycie loopState.Break() przed oznaczyć jako odpowiedział. (wersja równoległa była tak szybka, że musiałem przespać się w Parallel.ForEach, aby mieć nawet czas na anulowanie) – Paparazzi
Wygląda dobrze. Jeśli nie chcesz używać tokena anulowania, możesz usunąć obiekt opcji równoległej przekazany w wywołaniu Parallel.ForEach. BTW - ParallelOption służy również do ograniczenia liczby procesorów używanych do uruchamiania tego połączenia. –
W ustawieniach ustawiam ftspo.MaxDegreeOfParallelism = System.Environment.ProcessorCount; aby trzymać rzeczy ograniczone. – Paparazzi