gpt4 book ai didi

c# - 使用多线程进行慢速 Ms 互操作

转载 作者:行者123 更新时间:2023-12-03 13:23:29 27 4
gpt4 key购买 nike

我有一个程序可以在单击按钮时创建两个 pdf 文件。它在 WinForms 中使用 Microsoft Office 互操作,文件创建过程如下;

  • 用户在程序中工作
  • 点击按钮
  • 程序根据一个带有书签的模板创建一个word文件
  • 写入书签及其表
  • 保存为pdf
  • 关闭事件文档
  • 关闭单词 app
  • 关闭子窗体并切换到另一个

  • *用户看不到应用这个词

    它本身可以正常工作,但是完成这两个文件需要 8 秒,所以我尝试使用多线程,这样用户就不必等待,可以处理其他事情或再次进行第 1 步。

    但是,它会引发各种错误; COM、RPC 等甚至在数据库连接中,我认为原因是因为有两个单独的线程在工作并且它使用相同的资源,所以某个时间点另一个可能会关闭另一个线程的资源正在使用/即将使用
    所以我尝试使用join(),这样另一个线程可能先完成它的工作,关闭它各自的资源,然后继续下一个。

    这很好用,如果用户没有点击按钮来创建另一个文件(在用户完成第一步比预期更快的情况下)
    join()足以处理错误以及在后台创建文件,但是,我想处理文件创建紧随其后的情况,因为在这种情况下,它看起来像这个过程由于线程相互等待,所以它是线性的,除了它会产生瓶颈,其中线程现在排队并阻塞主线程,这使用户等待 12 秒或更长时间。

    我想知道/要澄清的是;
  • 我可以创建这两个使用 interop 的文件吗?使用不同的资源以免产生错误?
  • 我可以使用join() 的替代品吗?其中它不会阻塞 UI 线程或主线程?这样文件创建线程就在后台排队(仍然等待对方完成),而不会让用户等待。
  • 我是否错误地使用了 join() 或最终消耗更多时间的线程?

  • 这是我的代码;

    用于创建文档的模块中的过程和公共(public)变量:
    Public tsThread As Thread
    Public psThread As Thread

    Sub SaveDoc(docType,someArgs)
    Dim wordApp = New Word.Application
    Dim templateBookmarks As Word.Bookmarks
    Dim templateName As String
    Dim template As New Word.Document
    wordApp = CreateObject("Word.Application")

    Select Case docType
    Case "Type1"
    templateName = "SampleType.docx"
    template = wordApp.Documents.Add(templatePath & templateName)
    templateBookmarks = template.Bookmarks

    templateBookmarks.Item("bookmarkInWord").Range.Text = "Foo"
    template.Tables(1).Cell(msWordRow, 1).Range.Text = "Value in cell 1"
    Case "Type2"
    ‘Same thing, just different values and template
    Case "Type3"
    End select
    template.SaveAs2(savePath & saveName, Word.WdSaveFormat.wdFormatPDF)
    wordApp.ActiveDocument.Close(Word.WdSaveOptions.wdDoNotSaveChanges)
    wordApp.Quit()
    End Sub

    单击按钮时子窗体中的过程:
            If Not IsNothing(tsThread) Then
    If tsThread.IsAlive Then
    tsThread.Join()
    End If
    End If
    If Not IsNothing(psThread) Then
    If psThread.IsAlive Then
    psThread.Join()
    End If
    End If
    tsThread = New Thread(Sub() SaveDoc(docType1,someArgs))
    tsThread.Start()

    If Not IsNothing(tsThread) Then
    If tsThread.IsAlive Then
    tsThread.Join()
    End If
    End If
    psThread = New Thread(Sub() SaveDoc(docType2,someArgs))
    psThread.Start()

    If records = maxRecords Then
    If psThread.IsAlive or tsThread.isAlive Then
    tsThread.Join()
    psThread.Join()
    Dim fooThread = New Thread(Sub() SaveDoc(docType3,someArgs))
    fooThread.Start()
    End If
    End If
    SwitchForm("Child Form for Step 1")
    End Sub

    错误,即没有使用 join()通常在代码的这些部分中:
    wordApp.ActiveDocument.Close(Word.WdSaveOptions.wdDoNotSaveChanges)
    或在
    wordApp.Quit()
    或者在书签中
    templateBookmarks.Item("bookmarkInWord").Range.Text = "Foo"
    或者有时在不同时间或数据库连接过程中的任何情况下。

    我对多线程以及 Interop 女士还是比较陌生,所以如果我有任何误解,我会寻求帮助。代码在 VB 中,但我也可以理解 C#。非常感谢任何帮助/指导。谢谢!

    最佳答案

  • 我不会尝试一次使用多个线程中的任何单词/办公室互操作。以我的经验,这些事情本身就足够不可靠,而不会引入可能的并发问题。但这可能取决于您到底在做什么。
  • Thread 和 join 是处理多线程的相当老派的方法。较新的方法是使用 Tasks and async/await .这可能有助于强制执行一致的排序,而不会阻塞主线程。
  • 您通常应该避免从主线程执行时可能阻塞的任何方法,包括 .Join()。

  • 我会考虑使用生产者/消费者模式。当用户单击按钮时,主线程将生成要处理的文档,而后台线程将消耗文档并进行处理。一个 blocking collection通常可以用作两个线程之间的接口(interface)。

    另一种选择是 limited concurrency task scheduler .这使您可以安排任务进行处理,同时确保同时处理一个(或其他一些限制)。

    关于c# - 使用多线程进行慢速 Ms 互操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62086378/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com