我的C#应用程序遍历5000个文件,然后将xpath的值写入excel表格中的单元格。它每秒处理40个文件是相当慢的。
在分析之后,我发现这一行占所有使用时间的50%以上:
XmlDocument.Load(filename);
要写入excel,我循环遍历每个文件的每个xpath并执行以下操作:
worksheet.Cells[row, col] = value;
在速度方面,一次将所有xmls加载到内存中(每个xmls小于20kb ),然后将它们存储在一个集合中,然后将它们全部转置到excel中,会不会更有好处?
我知道多线程可能会降低性能,而不是提高性能,因为进程是IO受限的。
发布于 2012-02-06 20:29:14
它可能不受IO限制。大部分时间都花在构造XML DOM上。但是,多线程可能会引入一个问题,这取决于您将结果写入Excel的位置。我不确定,但如果您只能从单个线程访问Office对象,我不会感到惊讶。
在写入Excel对象之前,您必须添加一个收集结果的附加步骤。这必须是某种类型的同步集合,或者使用另一个专门用于写入Excel的线程,或者在处理完所有文件之后进行。
现在,回到第一点:大部分时间都花在加载DOM上。基于http://www.nearinfinity.com/blogs/joe_ferner/performance_linq_to_sql_vs.html的结果,如果您仍然需要与DOM相关的方法,我会考虑改用XDocument。它的界面并不离XmlDocument那么远,所以它应该是一个很容易适应的界面。
要获得最快的XML处理速度,请查看XmlReader。但是,这不会得到任何DOM函数,而且可能比两个基于DOM的方法更难处理。
因此,简而言之,首先尝试转换为XDocument方法,这可能会使您的速度提高一倍。然后,我将考虑将处理转换为多线程(可能在文件列表上使用PLINQ )。最后,如果性能仍然不够,请尝试使用XmlReader接口。
编辑以响应要使用的集合类型:
我看到了两种基本的选择,这取决于处理XML文件所需的时间。如果它只占整个过程的一小部分(大部分时间都花在处理excel上),只需创建一个List<T>
,其中T
是您需要写入到Excel中的数据的某种表示形式(如果这是您所需要的,它甚至可以是一个字符串),.Add
方法由lock
的方法括起来。
如果XML处理需要一段时间,并且您使用的是.Net 4,那么另一个选择就是查看ConcurrentQueue
类。这将提供线程本身的安全性(实际上,我现在看到,在第一种情况下也可以使用其中一个并发集合,无论是ConcurrentQueue
还是BlockingCollection
)。然后,您将拥有处理XML的线程,然后是一个写入Excel的使用者线程。
还有一些其他的东西。展开一个问题的注释,如果你没有做任何需要Excel特定函数的事情,你可以直接写到CSV。这里的http://www.codeproject.com/Articles/86973/C-CSV-Reader-and-Writer库使用起来相当简单,可以处理嵌入的逗号。这样做的缺点是,如果您尝试保存CSV,excel会抛出大的可怕对话框。然而,这些问题可能会通过用户培训来克服。
如果你的目标至少是Excel2007(尽管Excel2003可以读取带有插件的xlsx文件),另一种选择是使用OpenXML library生成Excel文件,前提是你还没有这样做。我想,由于这个库操作XML,它将比处理Excel互操作更快,也更安全(没有来自Excel的对话框,没有僵尸进程等)。
发布于 2012-02-06 22:38:41
在我看来,似乎大部分时间都花在了XML解析上,如果不解析XML,就无法做到这一点。所以我不认为有一个简单的答案。
https://stackoverflow.com/questions/9159911
复制相似问题