C# 限制进程的CPU使用

C# 限制进程的CPU使用,c#,optimization,background,performance,C#,Optimization,Background,Performance,我有一个正在运行的服务,它定期检查文件夹中的文件,然后对其进行处理。(读取数据、提取数据并将其存储在sql中) 所以我在一个测试箱上运行它,花费了Than预期的更长时间。 该文件有160万行,6小时后仍在运行(然后我回家) 问题是它运行的盒子现在完全瘫痪了——远程桌面超时了,所以我甚至不能上它来停止进程,或者连接调试器来查看到底有多远等等。 它的CPU占用率高达90%以上,而所有其他正在运行的服务或应用程序都受到了影响 代码是(来自内存,可能无法编译): List items=newlist()

我有一个正在运行的服务,它定期检查文件夹中的文件,然后对其进行处理。(读取数据、提取数据并将其存储在sql中)

所以我在一个测试箱上运行它,花费了Than预期的更长时间。 该文件有160万行,6小时后仍在运行(然后我回家)

问题是它运行的盒子现在完全瘫痪了——远程桌面超时了,所以我甚至不能上它来停止进程,或者连接调试器来查看到底有多远等等。 它的CPU占用率高达90%以上,而所有其他正在运行的服务或应用程序都受到了影响

代码是(来自内存,可能无法编译):

List items=newlist();
使用(StreamReader sr=fileInfo.OpenText())
{
而(!sr.EndOfFile)
{
字符串行=sr.ReadLine()
试一试{
字符串s=行。子字符串(0,8);
double y=double.Parse(line.Substring(8,7));
//如果该项不在集合中,请添加它。
if(items.Find(委托(ItemDTO i){return(i.Item==s);})==null)
项目。添加(新项目到(s,y));
}
捕获{/*崩溃*/}
}
退货项目;
}
- 所以我正在努力改进代码(任何提示都值得欣赏)

但它仍然可能是一个缓慢的事情,这是好的,我没有问题,它花了很长时间,只要它不杀死我的服务器

所以我想从你们这些好人那里得到的是: 1) 我的代码是否严重未优化? 2) 我可以限制代码块可能使用的CPU数量吗


干杯所有

您真的需要将所有数据保存在内存中吗?您可以将其存储在数据库中(如果您需要一些简单而有力的东西,请使用Sqlite)并使用sql进行处理。

您不能使用大容量加载此文件,然后在数据库服务器上进行处理吗

  • 对列表进行查找是一个O(n)操作,这意味着随着列表变长,搜索项目的时间也会变长。您可以考虑将这些项放入.NET 4/3.5中,或者使用.NET的早期版本,它可以充当索引,如果您需要列表中的项来保持原始顺序,则可以继续将它们放入列表中,但是使用哈希集/字典进行检查。

  • 您还可以在线程中运行此代码,这将有助于在进程运行时保持UI的响应性

  • 在回答1)时,我会使用排序列表(如果有大量冗余数据)或哈希字典而不是常规字典来加快搜索速度

    这将帮助您在这两种方法之间做出选择


    对于问题2),我将线程优先级设置为低于正常值。请参阅。

    与其限制其CPU使用,不如将其设置为空闲优先级,这样它只会在没有其他操作可供box执行时运行。其他人已经提到了优化的可能性,所以我不想讨论这一部分。

    在列表中找到的是O(n)。如果文件有160万行(即160万项),您将重复浏览超过100万行的列表,这将浪费大量时间

    正如其他人所建议的,如果要进行大量搜索,则需要更好的数据结构。为更快的搜索而设计的

    如果使用.NET3.5,则可以使用HashSet集合,它为搜索提供了一个摊销O(1)。或字典集合正在使用.NET 2.0

    接下来你要问自己,如果文件有160万行,你有足够的内存吗?如果这样做,则在内存中解析文件将比将其发送到数据库以处理重复文件更快,但如果内存不足,则将进行分页。很多(这就是现在可能发生的事情)。

    • 哈希集
    • 低优先级线程
    • 某种SQL批量插入

    正如其他人所说,修复数据结构

    现在,我的眼睛碰到了这样一句话:“定期检查文件夹中的文件,然后对其进行处理。”多久“定期”一次,为什么要处理一个可能没有更改的文件

    你可能想看看System.IO.FileSystemWatcher,我不是一个c#程序员,但我想看看逻辑

  • 每次在循环中都创建一个新的字符串对象。如果我必须用java来做, 我会使用StringBuffer,而不是使用string对象

  • 你的数据文件很大,所以我认为你应该有逻辑来清除文件中的信息 每“n”个记录之后的数据库。您需要额外的逻辑来记录 到目前为止,记录已被清除。或者,因为您的逻辑只捕获第一行数据 &忽略后续的重复项,而不是使用Find方法。您不能尝试插入吗 收集数据并捕获sql故障

  • 处理逻辑应该在单独的线程中,以保持系统响应


  • 通过使用固有且有效地强制执行唯一元素的数据结构,而不是每次自己调用列表上的
    Find
    ,您很可能会大大加快代码的速度,这可能是您大部分计算的地方。在其他语言中,这是一个“set”类,但我对C#不够精通,无法准确地告诉您这应该是哪个类。很可能是我现在开始获取的哈希集System.OutOfMemory异常被抛出。我仍然需要将其存储在内存中才能使用SqlBulkCopy,不是吗?事实上,我所知道的唯一方法就是在内存中创建一个DataTable对象,然后填充它。就像我已经。。
    List<ItemDTO> items = new List<ItemDTO>();
    using (StreamReader sr = fileInfo.OpenText())
    {
        while (!sr.EndOfFile)
        {
            string line = sr.ReadLine()
            try {
               string s = line.Substring(0,8);
               double y = Double.Parse(line.Substring(8,7));
    
               //If the item isnt already in the collection, add it.
               if (items.Find(delegate(ItemDTO i) { return (i.Item == s); }) == null)
                   items.Add(new ItemDTO(s,y));
             }
             catch { /*Crash*/ }
        }
        return items;
    }