excel - 为什么并行代码不能写入 Excel 电子表格?

标签 excel parallel-processing f# excel-interop

Excel 电子表格中编写许多工作表可能需要一段时间。并行化它会很有帮助。

此代码运行良好,它使一个 Excel 电子表格在屏幕上弹出,其中包含四个名为 Sheet112 的工作表3

open Microsoft.Office.Interop.Excel
open FSharp.Collections.ParallelSeq

let backtestWorksheets = [1..3]

let app = new ApplicationClass(Visible = true) 

let workbook = app.Workbooks.Add(XlWBATemplate.xlWBATWorksheet)

let writeInfoSheet (worksheet: Worksheet) : unit =

    let foo i =
        let si = string i
        worksheet.Range("A" + si, "A" + si).Value2 <- "Hello " + si
    List.iter foo [1..10]

let wfm = [1, writeInfoSheet; 2, writeInfoSheet; 3, writeInfoSheet]
          |> Map.ofList

let adder (workbook : Workbook)
          (i        : int)
                    : unit =

    let sheet = workbook.Worksheets.Add() :?> Worksheet
    sheet.Name <- string i
    wfm.[i] sheet

List.iter (adder workbook) backtestWorksheets
//PSeq.iter (adder workbook) backtestWorksheets

[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

但是,将以 List.iter 开头的行替换为其下方的注释行,会弹出一个包含相同四个工作表的电子表格,但所有工作表都是空白的。

所以我的问题是:为什么不能使用 PSeq 并行化代码写入 Excel?

备注:

最初我有一个不同的问题。也许是因为在我的应用程序中,当我尝试使用 PSeq 运行与上面类似的代码时,工作表更重,出现异常,显示

Unhandled Exception: System.TypeInitializationException: The type initializer for '<StartupCode$Fractal13>.$Program' threw an exception. ---> System.AggregateException: One or more errors occurred. ---> System.Runtime.InteropServices.COMException: The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))

List.iter 替换 PSeq.iter 就不会发生这种情况。

我无法在足够简单的上下文中复制此异常以成为一个正确的SO问题,但我仍然对处理它的任何建议感兴趣。

最佳答案

看起来 Microsoft.Office.Interop.Excel 代码从未被设计为同时从多个线程调用。 Here's a question someone asked在 MS Office 论坛中了解如何在多线程中进行更新(在 C# 中)。我将在这里引用该答案的相关部分:

Using multi-threading to search in multiple worksheets ends up with using the heart of Excel – the Excel.Application object, which means threads need to be queued to run one-at a time, depriving you of the desired performance improvement for the application.

[...]

All of this is because the Office object model isn't thread safe.

如果您调用 Microsoft.Office.Interop 命名空间中的任何内容,您似乎只能使用非并行设计。

编辑: Aaron M. Eshbach评论中有一个很好的建议:在多个线程上完成所有后台工作,并使用 MailboxProcessor 对电子表格进行实际更新。 MailboxProcessor 的消息队列将自动为您序列化更新操作,无需您进行额外的工作。

关于excel - 为什么并行代码不能写入 Excel 电子表格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50429380/

相关文章:

excel - 检查文件是否下载以恢复代码

Excel 多级数组公式,其中部分字符串匹配对结果单元格求和

c - CUDA 上的定时内核执行

parallel-processing - 使用 @everywhere 在 julia 中传递共享数组

excel - 如何使用 VBA 识别 ThisWorkbook 模块

excel - 使用 Excel 宏重新格式化单元格内容

sql-server - Talend Open Studio 是否有类似于 SSIS 的序列容器?

multithreading - 加入第一个完成的线程?

f# - 为自定义集合定义 cons (::) 运算符

asynchronous - Task.Delay(-1) 的 F# 等价物是什么?