繁体   English   中英

如何在过滤时将项目添加到集合?

[英]How to add items to a collection, while filtering it?

我有一些日志事件。 我为用户提供了过滤不同日志级别的能力。 在该筛选过程中,如果添加了新的日志事件,则会引发异常。 我可以在过滤集合时锁定它,但是这意味着将不会以正确的顺序或根本不会添加任何新的日志事件。

过滤方法:

//Filters and returns a list of filtered log events
    private IEnumerable<LogEvent> FilterLogEvents()
    {
        return (from x in LogEvents
                where ((ViewDebugLogs == true) ? x.Level == "Debug" : false)
                || ((ViewErrorLogs == true) ? x.Level == "Error" : false)
                || ((ViewInfoLogs == true) ? x.Level == "Info" : false)
                select x);
    }

如果我只返回一个列表,那么在中间查询中也会发生同样的事情。

如何在添加到集合的同时使用它? 如果将日志事件添加到中间过滤器中,则主要要确保将日志事件按正确的顺序添加到集合中。 因此,如果我不能同时添加日志事件,是否可以以某种方式将它们排队并在以后正确插入它们?

不可以,枚举时不能修改集合。 您可以在枚举期间复制集合,枚举副本并修改原始集合。

//the following example throws an exception
var numbers = GetTheNumbers();
foreach(var number in numbers)
{
    numbers.Add(1);   //exception thrown
}

//copy the collection first
var numbers = GetTheNumbers();
var copy = numbers.ToArray();
foreach(var number in copy)
{
    numbers.Add(1);  //safe
}

您可以在将一些并发集合添加到项目时对其进行迭代。 这样的集合之一就是ConcurrentQueue<T> ,如果满足以下条件,我认为它可能适合于日志:

  • 您只想在日志末尾添加项目。
  • 您无需一口气将其清空。 (而不是清空队列,您必须创建一个新的空队列,或者必须循环调用TryDequeue()直到它为空)。

请注意,当您遍历ConcurrentQueue<T> ,似乎在迭代开始时读取了计数,并且在迭代过程中未更新计数,因此,如果在迭代时添加了新项目,您将看不到它们(但是项目的添加不会引起异常)。

这是一个演示程序:

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    internal class Program
    {
        public static void Main()
        {
            var queue = new ConcurrentQueue<int>();

            Task.Run(() =>
            {
                for (int i = 0; i < 1000; ++i)
                {
                    queue.Enqueue(i);
                    Thread.Sleep(1);
                }
            });

            Thread.Sleep(100);
            Console.WriteLine($"Count before loop: {queue.Count}");

            foreach (var i in queue)
                Console.WriteLine($"{i}, n={queue.Count}");
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM