C# 多线程-线程池是一个不错的选择吗?

C# 多线程-线程池是一个不错的选择吗?,c#,multithreading,threadpool,C#,Multithreading,Threadpool,我有一个c#(.NET3.5)应用程序,可以导入数千个文件。现在,我为每个文件创建后台工作程序。它在一定的限制下工作良好&然后应用程序会随着系统内存不足异常而消亡。我假设这是因为大量线程。对于这种情况,threadpool是一个很好的解决方案吗 例外情况是: System.OutOfMemoryException | Exception of type 'System.OutOfMemoryException' was thrown. at System.Data.RBTree

我有一个c#(.NET3.5)应用程序,可以导入数千个文件。现在,我为每个文件创建后台工作程序。它在一定的限制下工作良好&然后应用程序会随着系统内存不足异常而消亡。我假设这是因为大量线程。对于这种情况,threadpool是一个很好的解决方案吗

例外情况是:

    System.OutOfMemoryException | Exception of type 'System.OutOfMemoryException' was thrown. 
    at System.Data.RBTree`1.TreePage..ctor(Int32 size)
    at System.Data.RBTree`1.AllocPage(Int32 size)
    at System.Data.RBTree`1.InitTree()
    at System.Data.Index.InitRecords(IFilter filter)
    at System.Data.Index..ctor(DataTable table, Int32[] ndexDesc, IndexField[] indexFields,           
    Comparison`1 comparison, DataViewRowState recordStates, IFilter rowFilter)
    at System.Data.DataTable.GetIndex(IndexField[] indexDesc, DataViewRowState recordStates, IFilter 
    rowFilter)
    at System.Data.DataColumn.get_SortIndex()
    at System.Data.DataColumn.IsNotAllowDBNullViolated()
    at System.Data.DataTable.EnableConstraints()
    at System.Data.DataTable.set_EnforceConstraints(Boolean value)
    at System.Data.DataTable.EndLoadData()
    at System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String    
    srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn    
    parentChapterColumn, Object parentChapterValue)
    at System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 
    startRecord, Int32 maxRecords)
    at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 
    startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
    at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32  
    maxRecords, IDbCommand command, CommandBehavior behavior)
    at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
    at Dms.Data.Adapters.DataTableAdapterBase`2.FillByCommand(TTbl table, DbCommand command)

问题很可能是您试图一次加载过多的文件

使用线程池可能会有所帮助,因为它可以为您提供一种限制处理的方法。但是,如果您正在导入和处理“数千个文件”,适当的方法可能是创建一个管道来处理您的处理,然后用您的文件填充管道(或一定数量的管道)。这将允许您控制并发量,并防止同时处理过多的单个文件。它可以将您的内存和处理需求保持在一个更合理的水平


编辑:


既然你(现在)提到你正在使用C#。。。BackgroundWorker实际上使用线程池。切换到直接使用线程池可能仍然是一个好主意,但它可能不会完全解决问题。您可能想考虑使用一些类似于建立生产者/消费者队列的方法。然后,您可以让一个或多个线程“消费”文件并处理它们,只需将所有文件添加到
BlockingCollection
。这将使您可以控制一次处理多少文件(只需添加另一个线程即可)。问题很可能是您试图一次加载太多文件

使用线程池可能会有所帮助,因为它可以为您提供一种限制处理的方法。但是,如果您正在导入和处理“数千个文件”,适当的方法可能是创建一个管道来处理您的处理,然后用您的文件填充管道(或一定数量的管道)。这将允许您控制并发量,并防止同时处理过多的单个文件。它可以将您的内存和处理需求保持在一个更合理的水平


编辑:


既然你(现在)提到你正在使用C#。。。BackgroundWorker实际上使用线程池。切换到直接使用线程池可能仍然是一个好主意,但它可能不会完全解决问题。您可能想考虑使用一些类似于建立生产者/消费者队列的方法。然后,您可以让一个或多个线程“消费”文件并处理它们,只需将所有文件添加到
BlockingCollection
。这将使您可以控制一次处理多少个文件(只要尽可能添加另一个线程进行处理即可)。

可以,是的。考虑只有有限数量的CPU或内核。只有多个线程可以并发运行。如果他们中的许多人正在等待另一台计算机上运行的其他进程(例如,如果你正在下载这些文件),那么你可以有更多的活动。仅仅因为您有一个单独的线程,并不意味着它增加了并发性。只是转换成本和内存分配(如您所见)。根据空闲时间的大小,尝试将池限制为仅比CPU略多的线程。从那里开始调整。

可以,是的。考虑只有有限数量的CPU或内核。只有多个线程可以并发运行。如果他们中的许多人正在等待另一台计算机上运行的其他进程(例如,如果你正在下载这些文件),那么你可以有更多的活动。仅仅因为您有一个单独的线程,并不意味着它增加了并发性。只是转换成本和内存分配(如您所见)。根据空闲时间的大小,尝试将池限制为仅比CPU略多的线程。从那里开始调整。

我认为这是一个不错的选择。然而,后台工作程序在某种程度上已被.NET4FramWorks所取代。这将根据您机器上的处理器数量进行优化,并相应地解决问题。也许你可以使用第三方物流和平行物流。您可以传入要运行的最大并发线程池线程数,以限制一次批量导入的文件数,例如:

ParallelOptions options = new ParallelOptions();  
options.MaxDegreeOfParallelism = 4;

可能对你有帮助吗?

我认为这是个不错的选择。然而,后台工作程序在某种程度上已被.NET4FramWorks所取代。这将根据您机器上的处理器数量进行优化,并相应地解决问题。也许你可以使用第三方物流和平行物流。您可以传入要运行的最大并发线程池线程数,以限制一次批量导入的文件数,例如:

ParallelOptions options = new ParallelOptions();  
options.MaxDegreeOfParallelism = 4;

可能对您有帮助吗?

如果我对您的理解正确,您需要实施生产者-消费者方法: 1) 一个生产者-产生文件列表(要导入)。 2) 多个(固定数量)使用者-执行导入


要实现这一点,您可以使用(自.NET4.0起)。文档中有一个示例。

如果我理解正确,您需要实施生产者-消费者方法: 1) 一个生产者-产生文件列表(要导入)。 2) 多个(固定数量)使用者-执行导入


要实现这一点,您可以使用(自.NET4.0起)。文档中有一个示例。

更新了问题。它是用c#表示的。如果你的应用程序是32位的,并且你在内存中加载了超过1.5 GB的数据,你可能会遇到内存不足的异常。有关更多信息,请参见此问题:那么您是否一次加载超过1.5 GB的数据?您是否将数千个文件中的数据导入应用程序中的某个内部集合,还是将数据放入数据库或类似的东西?我不知道您使用的是.net的哪个版本,但看看这个可能会有所帮助:我正在导入文件并将它们放入数据库中