Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将项目添加到集合中,同时对其进行筛选?_C#_Multithreading_Collections - Fatal编程技术网

C# 如何将项目添加到集合中,同时对其进行筛选?

C# 如何将项目添加到集合中,同时对其进行筛选?,c#,multithreading,collections,C#,Multithreading,Collections,我有一组日志事件。我让用户能够过滤出不同的日志级别。在过滤过程中,如果添加了新的日志事件,则会引发异常。我可以在过滤集合时锁定它,但是这意味着任何新的日志事件都不会以正确的顺序添加,或者根本不会添加(?) 过滤方法: //Filters and returns a list of filtered log events private IEnumerable<LogEvent> FilterLogEvents() { return (from x in

我有一组日志事件。我让用户能够过滤出不同的日志级别。在过滤过程中,如果添加了新的日志事件,则会引发异常。我可以在过滤集合时锁定它,但是这意味着任何新的日志事件都不会以正确的顺序添加,或者根本不会添加(?)

过滤方法:

//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);
    }
//筛选并返回筛选的日志事件列表
私有IEnumerable FilterLogEvents()
{
返回(来自LogEvents中的x)
其中((ViewDebugLogs==true)?x.Level==“Debug”:false)
||((ViewErrorLogs==true)?x.Level==“Error”:false)
||((ViewInfoLogs==true)?x.Level==“Info”:false)
选择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
}

您可以在向某些并发集合添加项时对其进行迭代。一个这样的集合是,如果满足以下条件,我认为它可能适合日志:

  • 您只希望在日志末尾添加项
  • 你永远不需要一次性清空它。(您需要创建一个新的空队列,而不是清空队列,或者必须循环调用
    TryDequeue()
    ,直到队列为空)
请注意,当您在
ConcurrentQueue
上迭代时,计数似乎在迭代开始时读取,而在迭代过程中不会更新,因此如果在迭代过程中添加了新项,您将看不到它们(但添加项不会导致异常)

下面是一个演示程序:

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}");
        }
    }
}
使用系统;
使用System.Collections.Concurrent;
使用系统线程;
使用System.Threading.Tasks;
名称空间演示
{
内部课程计划
{
公共静态void Main()
{
var queue=新的ConcurrentQueue();
Task.Run(()=>
{
对于(int i=0;i<1000;++i)
{
排队。排队(i);
睡眠(1);
}
});
睡眠(100);
WriteLine($“循环前计数:{queue.Count}”);
foreach(队列中的变量i)
WriteLine($“{i},n={queue.Count}”);
}
}
}

什么类型是
LogEvents
?尝试使用并发数据结构:。或者你可以尝试过滤列表的副本,而不是原始列表。它是一种包含与事件相关信息的类型,例如级别、消息、时间戳等。我已将其添加到post@douglasg14b我想他问的是
LogEvent*s*
,而不是
LogEvent
@MatthewWatson,
LogEvents
只是
LogEvent
的集合。啊!使用线程安全的集合是有意义的,在向集合添加项目之前,我从未修改过该集合,因此它可以完美地工作。我只需要弄清楚如何将查询中未捕获的日志条目获取到新的筛选集合。不过我很确定我能应付。