использование ThreadPools для поиска по спискам объектов

StackOverflow https://stackoverflow.com/questions/377039

  •  22-08-2019
  •  | 
  •  

Вопрос

У меня есть эти объекты-контейнеры (назовем их Контейнер) в списке.Каждый из этих объектов-контейнеров, в свою очередь, имеет DataItem (или производное) в списке.В типичном сценарии у пользователя будет 15-20 объектов-контейнеров с 1000-5000 DataItems каждый.Тогда есть некоторые DataMatcher объекты, которые можно использовать для различных типов поиска.В основном они работают нормально (поскольку у меня есть несколько сотен модульных тестов), но для того, чтобы мое WPF-приложение выглядело быстрым и отзывчивым, я решил, что мне следует использовать ThreadPool для этой задачи.Таким образом, у меня есть DataItemCommandRunner который запускается на объекте-контейнере и в основном выполняет каждый делегат в списке, который он принимает в качестве параметра для каждого DataItem по очереди;Я использую ThreadPool ставить в очередь один поток для каждого Контейнера, чтобы теоретически поиск был максимально эффективным на многоядерных компьютерах и т. д.

В основном это делается в DataItemUpdater класс, который выглядит примерно так:

public class DataItemUpdater
{
    private Container ch;
    private IEnumerable<DataItemCommand> cmds;

    public DataItemUpdater(Container container, IEnumerable<DataItemCommand> commandList)
    {
        ch = container;
        cmds = commandList;
    }

    public void RunCommandsOnContainer(object useless)
    {
        Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
        foreach (DataItem di in ch.ItemList)
        {
            foreach (var cmd in cmds)
            {
                cmd(sh);
            }
        }
        //Console.WriteLine("Done running for {0}", ch.DisplayName);
    }
}

(Бесполезный параметр объекта для Запуститькоммандсонконтейнер потому что я экспериментирую с потоками и без них, и один из них требует некоторого параметра.Кроме того, установив приоритет Выше нормального это тоже эксперимент)

Это отлично работает для всех сценариев, кроме одного — когда я использую AllWordsMatcher тип объекта, который будет искать DataItem объекты, содержащие все искомые слова (в отличие, например, от любых слов, точной фразы или регулярного выражения).

Это довольно просто somestring.Contains(eachWord) основанный объект, поддерживаемый модульными тестами.Но здесь кроется некоторая странность.

Когда Запуститькоммандсонконтейнер работает с использованием ThreadPool потоков, это вернет безумные результаты.Скажем, у меня есть такая строка:

var someString = "123123123 - just some numbers";

И я запускаю это:

var res = someString.Contains("data");

Когда он запускается, он на самом деле довольно часто возвращает true - у меня есть отладочная информация, которая показывает, что он возвращает true для пустых строк и других строк, которые просто не содержат данных.Кроме того, иногда он возвращает false, даже если строка действительно содержит искомые данные.

Кикер во всем этом?Почему я подозреваю, что ThreadPool а не мой собственный код?

Когда я запускаю ВыполнитьКомандыОнКонтейнер() команда для каждого контейнера в моем основном потоке (т.е.блокировка интерфейса и все), работает на 100% корректно - каждый раз!Он никогда не находит того, чего не должен был бы найти, и никогда не пропускает ничего, что должен был найти.

Однако, как только я использую ThreadPool, он начинает находить много предметов не должен, хотя иногда не находит нужные предметы.

Я понимаю, что это сложная проблема (это точно, пытаться отладить больно!), Но я буду очень признателен за любое понимание того, почему и как это исправить!

Спасибо!

Руна

Это было полезно?

Решение

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

В более общем плане я бы рассмотрел все экземпляры, участвующие в процессе сопоставления/поиска, особенно рабочие объекты, используемые при многопоточной работе.Судя по прошлому опыту, проблема обычно кроется именно в этом.(В этом случае легко слишком долго смотреть на граф объектов, представляющий контейнер/элемент данных вашего бизнес-данных)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top