Перебор растущего списка и запоминания позиции

#c# #list #hashset

#c# #Список #hashset

Вопрос:

Что я пытаюсь сделать, добавьте существующий список из другого класса / потока (который постоянно растет) в новый список, содержащий значения, подлежащие проверке. Но я не уверен, как это сделать, не обрабатывая одни и те же значения снова и снова. Я просто хотел бы обработать новейшие добавленные значения. Смотрите приведенный ниже код

 public static void ParsePhotos()
        {
            int tmprow = 0;
            string checkthis = "";

            List<String> PhotoCheck = new List<String>();

            while (Core.Hashtag.PhotoUrls.Count > Photocheck.Count)
                {

                    foreach (string photourl in Core.Hashtag.PhotoUrls)
                    {
                        PhotoCheck.Add(photourl);
                    }

                    checkthis = PhotoCheck[tmprow];

                    //validate checkthis here
                    
                    //add checkthis to new list if valid here

                    tmprow  ;

                    while (Thread.Sleep(10000);

                };
           }
 

HashSet<String>Core.Hashtag.PhotoUrls обновляется каждые несколько секунд в другом потоке.

Комментарии:

1. Звучит как вариант использования для обработчика очередей. Я бы не стал постоянно добавлять что-то в список.

Ответ №1:

Нет никаких практических способов сделать это таким образом, поскольку HashSet это неупорядоченные коллекции. Обычные коллекции также не являются потокобезопасными и не должны использоваться без блокировки при использовании нескольких потоков.

Типичным способом сделать это было бы использовать параллельную очередь, где проверка удаляет элементы из очереди и добавляет их в другую очередь. Поток, который создает элементы, должен быть изменен, чтобы добавлять элементы в параллельную очередь вместо или в дополнение к HashSet.

     public static Task ValidateOnWorkerThread<T>(
        BlockingCollection<T> queue, 
        Func<T, bool> validateMethod, 
        ConcurrentBag<T> validatedItems,
        CancellationToken cancel)
    {
        return Task.Run(ProcessInternal, cancel);
        void ProcessInternal()
        {
            foreach (var item in queue.GetConsumingEnumerable(cancel))
            {
                if (validateMethod(item))
                {
                    validatedItems.Add(item);
                }
            }
        }
    }
 

Это также имеет преимущество обработки элементов в режиме реального времени вместо необходимости все время спать.