C# 内存不足异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/505882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:02:58  来源:igfitidea点击:

Out of Memory Exception

c#asp.netmemory-management

提问by jumbojs

I am working on a web app using C# and asp.net I have been receiving an out of memory exception. What the app does is read a bunch of records(products) from a data source, could be hundreds/thousands, processes those records through settings in a wizard and then updates a different data source with the processes product information. Although there are multiple DB classes, right now all the logic is in one big class. The only reason for this, is all the information has to do with one thing, a product. Would it help the memory if I divided my app into different classes?? I don't think it would because if I divided the business logic into two classes, both of the classes would remain alive the entire time sending messages to each other, and so I don't know how this would help. I guess my other solution would be to find out what's sucking up all the memory. Is there a good tool you could recommend??

我正在使用 C# 和 asp.net 开发 Web 应用程序,但收到内存不足异常。该应用程序所做的是从数据源读取一堆记录(产品),可能是成百上千,通过向导中的设置处理这些记录,然后使用流程产品信息更新不同的数据源。尽管有多个 DB 类,但现在所有的逻辑都在一个大类中。这样做的唯一原因是所有信息都与一件事有关,即产品。如果我将我的应用程序分成不同的类,它会帮助记忆吗?我不认为会这样,因为如果我将业务逻辑分为两个类,那么这两个类在相互发送消息的整个过程中都会保持活动状态,所以我不知道这会有什么帮助。我想我的另一个解决方案是找出什么' s 吸光了所有的记忆。有什么好的工具可以推荐吗??

Thanks

谢谢

采纳答案by Sam Saffron

Are you using datareaders to stream through your data? (to avoid loading too much into memory)

您是否使用数据读取器来流式传输数据?(避免加载太多内存)

My gut is telling me this is a trivial issue to fix, don't pump datatables with 1 million records, work through tables one row at a time, or in small batches ... Release and dispose objects when you are done with them. (Example: don't have static List<Customer> allCustomers = AllCustomers())
Have a development rule that ensures no one reads tables into memory if there are more than X amount of rows involved.

我的直觉告诉我这是一个需要解决的微不足道的问题,不要用 100 万条记录抽取数据表,一次处理一行,或者小批量处理......当你完成它们时释放和处置对象。(例如:没有static List<Customer> allCustomers = AllCustomers()
制定一项发展规则,确保如果涉及的行数超过 X,则没有人将表读入内存。

If you need a tool to debug this look at .net memory profileror windbg with the sos extensionboth will allow you to sniff through your your managed heaps.

如果你需要一个工具来调试这个看看.net memory profiler带有 sos 扩展的windbg两者都将允许你嗅探你的托管堆。

Another note is, if you care about maintainability and would like to reduce your defect count, get rid of the SuperDuperDoEverything class and model information correctly in a way that is better aligned with your domain. The SuperDuperDoEverything class is a bomb waiting to explode.

另一个注意事项是,如果您关心可维护性并希望减少缺陷数量,请以更符合您的领域的方式正确删除 SuperDuperDoEverything 类和模型信息。SuperDuperDoEverything 类是一颗等待爆炸的炸弹。

回答by Matt Davison

Start with Perfmon; There is a number of counters for GC related info. More than likely you are leaking memory(otherwise the GC would be deleting objects), meaning you are still referencing data structures that are no longer needed.

从 Perfmon 开始;GC 相关信息有许多计数器。您很可能正在泄漏内存(否则 GC 将删除对象),这意味着您仍在引用不再需要的数据结构。

回答by Mostlyharmless

You should split into multiple classes anyways, just for the sake of a sane design.

无论如何,你应该分成多个类,只是为了一个理智的设计。

Are you closing your DB connections? If you are reading into files, are you closing/releasing them once you are done reading/writing? Same goes for other objects.

您要关闭数据库连接吗?如果您正在读入文件,是否在完成读/写后关闭/释放它们?其他对象也是如此。

You could cycle your class objects routinely just to release memory.

您可以定期循环类对象以释放内存。

回答by z3r0 c001

a very basic thing you might want to try is, restart visual studio (assuming you are using it) and see if the same thing happens, and yes releasing objects without waiting for garbage collector is always a good practice.

您可能想要尝试的一个非常基本的事情是,重新启动 Visual Studio(假设您正在使用它)并查看是否会发生同样的事情,并且是的,不等待垃圾收集器就释放对象始终是一个好习惯。

to sum it up,

把它们加起来,

  • release objects
  • close connections
  • 释放对象
  • 密切联系

and you can always try this, http://msdn.microsoft.com/en-us/magazine/cc337887.aspx

你可以随时尝试这个, http://msdn.microsoft.com/en-us/magazine/cc337887.aspx

回答by Cory Foy

Also note that you may not actually be running out of memory. What happens is that .NET goes to look for contiguous blocks of memory, and if it doesn't find any, it throws an OOM - even if you have plenty of total memory to cover the request.

另请注意,您实际上可能不会耗尽内存。发生的情况是 .NET 去寻找连续的内存块,如果没有找到,它会抛出一个 OOM - 即使你有足够的总内存来满足请求。

Someone referenced both Perfmon and WinDBG. You could also setup adplus to capture a memory dump on crash - I believe the syntax is adplus -crash -iis. Once you have the memory dump, you can do something like:

有人同时引用了 Perfmon 和 WinDBG。您还可以设置 adplus 以捕获崩溃时的内存转储 - 我相信语法是adplus -crash -iis. 获得内存转储后,您可以执行以下操作:

.symfix C:\symbols
.reload
.loadby sos mscorwks
!dumpheap -stat

And that will give you an idea for what your high-memory objects are.

这将使您了解高内存对象是什么。

And of course, check out Tess Fernandez'sexcellent blog, for example this article on Memory Leaks with XML Serializersand how to troubleshoot them.

当然,请查看Tess Fernandez 的优秀博客,例如这篇关于XML 序列化程序的内存泄漏以及如何排除故障的文章。

If you are able to repro this in your dev environment, and you have VS Team Edition for Developers, there are memory profilers built right in. Just launch a new performance session, and run your app. It will spit out a nice report of what's hanging around.

如果你能够在你的开发环境中重现它,并且你有 VS Team Edition for Developers,那么就有内置的内存分析器。只需启动一个新的性能会话,然后运行你的应用程序。它会吐出一个很好的报告,说明周围有什么。

Finally, make sure your objects don't define a destructor. This isn't C++, and there's nothing deterministic about it, other than it guarantees your object will survive a round of Garbage Collection since it has to be placed in the finalizer queue, and then cleaned up the next round.

最后,确保您的对象没有定义析构函数。这不是 C++,它没有任何确定性,除了它保证您的对象将在一轮垃圾收集中幸存下来,因为它必须被放置在终结器队列中,然后在下一轮清理。

回答by jumbojs

I found the problem. While doing my loop I had a collection that wasn't being cleared and so data just keep being added to it.

我发现了问题。在做我的循环时,我有一个没有被清除的集合,所以数据一直被添加到其中。