3

私は以下のようなリストを持っています:

private List<DateTime> _result = new List<DateTime();

そして、私はそれに値を追加します

_result.Add(DateTime.Now);

要件は、追加された各アイテムを 5 分の期限内にリストから削除することです。

リストを1分ごとにチェックして古いアイテムを見つけて削除するタイマーを作成できると思っていましたが、もっと簡単な方法があるといいのですが?

それを実装する方法は?

ありがとう

4

2 に答える 2

5

これに対する私の見解は次のとおりです。

public class DateWrapper
{
    private ConcurrentBag<DateWrapper> list;
    private DateTime time;

    public DateTime Time
    {
        get { return time; }
    }

    private Timer timer;

    public DateWrapper(ConcurrentBag<DateWrapper> _list, DateTime _time)
    {
        list = _list;
        time = _time;

        list.Add(this);

        timer = new Timer();
        timer.Interval = 300000; // 5 Minutes
        timer.Tick += new EventHandler(Tick);
        timer.Start();
    }

    private void Tick(object sender, EventArgs e)
    {
        list.Remove(this);
    }
}

上記は、アイテムの小さなリストで機能します。リストが大きすぎると、タイマーが多すぎて...パフォーマンスが低下します。

したがって、多くのアイテムを処理する必要がある場合は、一般的な方法を次に示します。

public class ExpirableList<T> : IList<T>
{
    private volatile List<Tuple<DateTime, T>> collection = new List<Tuple<DateTime,T>>();

    private Timer timer;

    public int Interval
    {
        get { return timer.Interval; }
        set { timer.Interval = value; }
    }

    private TimeSpan expiration;

    public TimeSpan Expiration
    {
        get { return expiration; }
        set { expiration = value; }
    }

    /// <summary>
    /// Define a list that automaticly remove expired objects.
    /// </summary>
    /// <param name="_interval"></param>
    /// The interval at which the list test for old objects.
    /// <param name="_expiration"></param>
    /// The TimeSpan an object stay valid inside the list.
    public ExpirableList(int _interval, TimeSpan _expiration)
    {
        timer = new Timer();
        timer.Interval = _interval;
        timer.Tick += new EventHandler(Tick);
        timer.Start();

        expiration = _expiration;
    }

    private void Tick(object sender, EventArgs e)
    {
        for (int i = collection.Count - 1; i >= 0; i--)
        {
            if ((DateTime.Now - collection[i].Item1) >= expiration)
            {
                collection.RemoveAt(i);
            }
        }
    }

    #region IList Implementation
    public T this[int index]
    {
        get { return collection[index].Item2; }
        set { collection[index] = new Tuple<DateTime, T>(DateTime.Now, value); }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return collection.Select(x => x.Item2).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return collection.Select(x => x.Item2).GetEnumerator();
    }

    public void Add(T item)
    {
        collection.Add(new Tuple<DateTime, T>(DateTime.Now, item));
    }

    public int Count
    {
        get { return collection.Count; }
    }

    public bool IsSynchronized
    {
        get { return false; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public void CopyTo(T[] array, int index)
    {
        for (int i = 0; i < collection.Count; i++)
            array[i + index] = collection[i].Item2;
    }

    public bool Remove(T item)
    {
        bool contained = Contains(item);
        for (int i = collection.Count - 1; i >= 0; i--)
        {
            if ((object)collection[i].Item2 == (object)item)
                collection.RemoveAt(i);
        }
        return contained;
    }

    public void RemoveAt(int i)
    {
        collection.RemoveAt(i);
    }

    public bool Contains(T item)
    {
        for (int i = 0; i < collection.Count; i++)
        {
            if ((object)collection[i].Item2 == (object)item)
                return true;
        }

        return false;
    }

    public void Insert(int index, T item)
    {
        collection.Insert(index, new Tuple<DateTime, T>(DateTime.Now, item));
    }

    public int IndexOf(T item)
    {
        for (int i = 0; i < collection.Count; i++)
        {
            if ((object)collection[i].Item2 == (object)item)
                return i;
        }

        return -1;
    }

    public void Clear()
    {
        collection.Clear();
    }
    #endregion
}
于 2012-11-07T09:25:40.903 に答える
0

リストを反復処理して不要な要素を削除するバックグラウンド スレッドを使用できます。

public void RemoveDates()
        {
            var checkDatesTask= new Task(
                () =>
                    {
                        while (!_cancelationTokenSource.IsCancellationRequested)
                        {
                            //TODO: check and delete elements here

                            _cancelationTokenSource.Token.WaitHandle.WaitOne(
                                TimeSpan.FromSeconds(
                                   5));
                        }
                    },
                _cancelationTokenSource.Token,
                TaskCreationOptions.LongRunning);
            checkDatesTask.Start();
        }

ps非同期についてもっと読むことをお勧めします。オペレーション。

于 2012-11-07T09:23:59.350 に答える