3

我必须对 10,000 多个 Excel 文件应用简单的格式。我已经有一个多核程序正在运行。它为每个 Excel 文件打开一个新的 Excel 实例。如果重要,此代码当前位于我的表单代码中。

我希望将一个 Excel 实例与许多工作簿一起使用。如果我只使用一个 Excel 实例,是否可以使用多核功能?如何?

- 如果上述答案是否定的,一个更复杂的问题可能是:我应该生成多少个 Excel 实例,以及如何在每个实例之间拆分工作簿?

当前代码在这里:

private void SelectFilesButtonClick(object sender, EventArgs e)
{
   var listOfExcelFiles = OpenExcel.FileNames.ToList();
   Parallel.ForEach(listOfExcelFiles, TrivialExcelEditFunction);
}

private void TrivialExcelEditFunction(string file)
{
   //Open instance of Excel
   //Do processing
   //Close instance of Excel
}

更新了下面的代码,但仍不限于适当的内核数量。不知道为什么。

private void SelectFilesButtonClick(object sender, EventArgs e)
{
   var listOfExcelFiles = OpenExcel.FileNames.ToList();
   int cores = Environment.ProcessorCount;

   //Split one list into list of lists. Number of lists based on number of cpu cores
   List<List<object>> listOfLists = Split(listOfExcelFiles, cores);

   //Limits number of threads to number of cores
   Parallel.ForEach(listOfLists, new ParallelOptions { MaxDegreeOfParallelism = cores }, EditExcel);
}

private void TrivialExcelEditFunction(string file)
{
   //Open instance of Excel

   foreach (string file in files)
   {
       //Do processing
   }
   //Close instance of Excel
}

假设我有 4 个核心。我的想法是将文件列表分成 4 个相等的列表,将线程限制为 4 个,然后我就可以在 4 个 Excel 实例中处理文件。我认为这意味着 TrivialExcelEditFunction 只会运行 4 次。相反,这个函数运行了 14 到 27 次。请告诉我哪里出错了。

4

3 回答 3

2

正如@Servy 指出的那样,您可以创建多个线程,每个线程一个 Excel 实例。

确保每个线程都创建它正在使用的 Excel 对象。

期待诡异。拥有 10,000 多个文件,您可能至少会遇到一些小问题。如果隐藏的 Excel 实例试图提示用户,它可能会显示为冻结状态。

Word 在使用一些调用单线程 COM 对象的函数时会出现一些问题,我怀疑 Excel 可能也有一些问题。在 Word 中,这些以各种方式表现出来,包括实例冻结或关闭。

如果格式非常简单并且您的文件是 xmlx,那么编写一些代码以通过 OOXML SDK 应用更改可能是可行的,这不需要实际的 Excel 实例

于 2013-01-25T20:10:51.233 回答
2

创建 N 个任务/线程来执行处理,其中“N”是您机器上的内核数。给每个任务/线程一个Excel.

您将无法从多个线程控制单个实例(至少不能有效;它一次只能处理一个线程的任务),并且创建如此多的 Excel 实例效率非常低。

于 2013-01-23T15:03:26.417 回答
1

我认为这就是@Servy 上面所指的。我现在每天都在我正在使用的一段代码中使用它,它确实可以处理 Excel,而且肯定还没有失败。还要确保正确编组 COM 对象。还有一点额外的信息,Excel 2010 在内部使用多核,注意性能(尤其是大文件)。

var tasks = new Task[Environment.ProcessorCount];

for (int i = 0; i< Environment.ProcessorCount; i++)
{
    tasks [i] = Task.Factory.StartNew(() =>
    {
        // your Excel code here.                 
    });
}

Task.WaitAll(tasks);
于 2013-01-25T19:52:55.177 回答