Есть ли «простой способ» создать очередь, в которой itens удаляются из очереди через определенное время? (C#)

У меня тут небольшая проблема, и мне нужна помощь.

Мой код - это бесконечный поиск на веб-страницах шаблонов, которые, когда он находит что-то новое, записывает это в файл.

Однако иногда информация, которую я собираю, уже находится в файле, но не обновляется, и мне не нужны повторяющиеся записи в моем файле.

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

Вы можете ясно видеть, почему это плохая идея ... Поскольку он работает круглосуточно, 7 дней в неделю, этот список будет бесконечно увеличиваться. Но есть загвоздка. Я на 100% уверен, что информация, которую я ищу, никогда не повторится, если прошло 15 минут.

Итак, что я действительно хочу, так это исключить элементы, которые находятся в этом списке, в течение 15 минут. Я просто не могу придумать что-нибудь простое и / или элегантное, чтобы сделать это. Или я не знаю, есть ли какая-то структура данных или библиотека, которые могут решить эту проблему за меня.

Вот почему я спрашиваю здесь: как лучше всего создать своего рода «временный список», где элементы, которые есть какое-то время, удаляются в конце итерации?

Заранее спасибо.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
91
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы пробовали встроенный в .NET ПамятьКэш?

Вы можете установить политику кеширования, которая включает абсолютный тайм-аут, что, я думаю, вам и нужно.

Вам понадобится что-то работающее, что периодически сокращает список.

В прошлом я делал следующее:

  1. Используйте ConcurrentBag<Tuple<DateTime, T>> вместо List<T>
  2. С пакетом кортежей сохраните объект и время его добавления: theBag.Add(Tuple.Create(DateTime.Now, myObject));
  3. Запустите вторичный поток, который периодически перечисляет сумку и удаляет все записи, срок действия которых истек.

Это более активный подход, но он довольно простой. Однако, поскольку теперь вы работаете с двумя потоками, вы должны быть осторожны, чтобы не зайти в тупик. Поэтому я использовал что-то вроде ConcurrentBag. Вы также можете посмотреть другие коллекции Concurrent. Вы упомянули очередь, поэтому можете попробовать ConcurrentQueue

Внимательно изучите библиотеку кеширования, как предлагали другие, и взвесьте свои варианты. Полная библиотека кеширования может оказаться излишней.

ConcurrentBag использует локальное хранилище потоков и имеет низкую производительность в вашем сценарии. Его лучше всего использовать, когда каждый поток одновременно производит и потребляет, чтобы избежать снижения производительности при краже элементов.
Zer0 02.05.2018 04:12

Хорошо поймал. Я не знал о локальной копии потока. В этом случае он по-прежнему будет работать, но производительность снизится. Тем не менее, я считаю, что основной принцип хранения Tuple<DateTime, T> - хороший. Вы даже можете использовать простую старую очередь и проверять дату при выходе из очереди. Если он истек, просто продолжайте.

Adam Schiavone 02.05.2018 04:19

Спасибо, нашел ссылку здесь. Не возражайте против вашего простого дизайна.

Zer0 02.05.2018 04:24

Вместо списка строк создайте класс, имеющий свойство строки и свойство отметки времени. При создании экземпляра класса автоматически заполняйте свойство отметки времени значением DateTime.Now.

Каждый раз, когда вы просматриваете список, чтобы увидеть, существует ли строка, также проверяйте свойство timestamp и отбрасывайте любой элемент старше 15 минут.

пример

class TimeStampedSearchResult
{
    public string SearchResult { get; set; }

    public DateTime TimeStamp { get; private set; }

    public TimeStampedSearchResult(string searchResult)
    {
        SearchResult = searchResult;
        TimeStamp = DateTime.Now;
    }

    public void UpdateTimeStamp()
    {
        TimeStamp = DateTime.Now;
    }
}

тогда вы можете использовать это как:

public SearchForever()
{
    //the results list
    List<TimeStampedSearchResult> results = new List<TimeStampedSearchResult>();
    //a list of expired results to remove from results list
    List<TimeStampedSearchResult> expiredResults = new List<TimeStampedSearchResult>();
    while (true)
    {
        //search for a result
        var searchResult = new TimeStampedSearchResult(SearchForStuff());
        bool found = false;
        //iterate our list
        foreach (var result in results)
        {
            if (result.SearchResult == searchResult.SearchResult)
            {
                result.UpdateTimeStamp();
                found = true;
            }
            else
            {
                if (result.TimeStamp < DateTime.Now.AddMinutes(-15))
                {
                    expiredResults.Add(result);
                }
            }
        }
        if (!found)
        {
            //add to our results list
            results.Add(searchResult);
            //write result to file
            WriteResult(searchResult.SearchResult, "myfile.txt")
        }

        //remove expired results
        foreach (var oldResult in expiredResults)
            results.Remove(oldResult);

        //make sure you clear the expired results list too.
        expiredResults.Clear();
    }
}

Буквально изобретая колесо MemoryCache.

Zer0 02.05.2018 04:27

Другие вопросы по теме