是否可以在一个Excel实例中使用多核?

时间:2013-01-23 13:48:54

标签: c# excel multicore

我必须将简单格式应用于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次之间运行。请告诉我哪里出错了。

3 个答案:

答案 0 :(得分:2)

创建N个任务/线程以执行处理,其中“N”是计算机上的核心数。为每个任务/线程提供一个Excel

的实例

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

答案 1 :(得分:2)

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

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

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

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

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

答案 2 :(得分: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);