我在实体框架中循环遍历许多不同的对象,抓取一些相关数据并保存该数据。我正在为每个项目打开一个新线程,因为它需要一段时间来完成方法中的工作。但是,我的内存异常会导致几千个项目进入循环。我试图弄清楚这个问题发生在哪里以及如何保持多线程功能,但修复错误。任何帮助是极大的赞赏。谢谢。
foreach (var prod in products)
{
try
{
new Thread(() =>
{
ParsePage(prod);
}).Start();
counter++;
Console.WriteLine(counter);
}
catch (Exception ex)
{
string message = ex.Message;
}
}
public void ParsePage(Product p)
{
//New Repository
IDataRepository repo = new DataRepository();
//Grab related page report
PageReport pr = repo.PageReports.Where(c => c.ThePageType == "Product").FirstOrDefault(c => c.ThePageTypeID == p.ProductID);
//Do some stuff
//Save
repo.SavePageReport(pr);
}
答案 0 :(得分:2)
由于每个帖子都有default stack size of 1 MB,因此可能内存不足。 2000启动线程意味着2 GB的堆栈,可能是max on your system:
Windows *上应用程序的内存限制
32位
- 静态数据 - 2GB
- 动态数据 - 2GB
- 堆栈数据 - 1GB(堆栈大小由链接器设置,默认值为1MB。可以使用链接器属性系统>堆栈保留大小来增加)
请注意,在32位Windows上,所有类型数据的总和必须为2GB或更少。由于Windows本身使用的空间,实际限制约为1.75GB
64位
- 静态数据 - 2GB
- 动态数据 - 8TB
- 堆栈数据 - 1GB(堆栈大小由链接器设置,默认值为1MB。可以使用链接器属性系统>堆栈保留大小来增加)
有关详细信息,另请参阅此article by Raymond Chen和此stackoverflow question。
正如KroaX所说,较新的task和较旧的threadpool库旨在处理这样的情况。它们在线程和任务之间提供了额外的抽象级别,允许您轻松创建数千个轻量级任务,这些任务将在线程可用时分配给它们。
答案 1 :(得分:1)
如果您对整个操作使用相同的DbContext,则其缓存可能会导致内存不足错误。在解析和存储XML文件中的大量数据时,我遇到了类似的情况。
你应该像dbc建议的那样使你的存储库是一次性的,然后将它包装在using子句中:
public void ParsePage(Product p)
{
using (var repo = new DataRepository())
{
//Grab related page report
PageReport pr = repo.PageReports.Where(c => c.ThePageType == "Product").FirstOrDefault(c => c.ThePageTypeID == p.ProductID);
//Do some stuff
//Save
repo.SavePageReport(pr);
}
}
可以找到有关如何实施一次性模式的信息here