【问题标题】:axacropdflib - set source from worker threadaxacropdflib - 从工作线程设置源
【发布时间】:2013-11-06 19:24:53
【问题描述】:

我有一个 vb.net 项目,它的左侧是 pdf 的树形视图,右侧是 acrobat AxAcroPDF 查看器控件。单击树视图中的一个项目,我得到 fileinfo.fullname 值并将其传递给 AxAcroPDF src 属性。

在测试时,我注意到 pdf 加载速度很慢并且会阻塞我的 ui 线程,因此我认为工作线程将是在后台延迟加载这些 pdf 的好帮手。

当我使用工作线程的 DoWork 方法运行我的代码并尝试更新我的 pdfviewer 对象时,我得到一个无效的强制转换异常。

System.InvalidCastException 被捕获 HResult=-2147467262
消息=无法将“System.__ComObject”类型的 COM 对象转换为 接口类型“AcroPDFLib.IAcroAXDocShim”。此操作失败 因为接口的 COM 组件上的 QueryInterface 调用 使用 IID '{3B813CE7-7C10-4F84-AD06-9DF76D97A9AA}' 失败,因为 以下错误:不支持此类接口(来自 HRESULT 的异常: 0x80004002 (E_NOINTERFACE))。来源=mscorlib 堆栈跟踪: 在 System.StubHelpers.StubHelpers.GetCOMIPFromRCW(对象 objSrc,IntPtr pCPCMD,IntPtr& ppTarget,布尔& pfNeedsRelease) 在 AcroPDFLib.IAcroAXDocShim.set_src(字符串 pVal) 在 AxAcroPDFLib.AxAcroPDF.set_src(字符串值) 在 myapp.fill_treeview_with_filesfolders_doked_andthreads.LoadPDFInBackground(字符串 选定文件)在 C:\Users\me\Desktop.....\fill_treeview_with_filesfolders_doked_andthreads.vb:line 84 内部异常:

我在网上找不到任何其他关于此异常详细信息的线程,所以我不确定这里的问题是什么。我认为我的问题与跨线程访问冲突有关,但即使我将 Control.Checkforillegalcrossthreadcalls 设置为 false,我也会遇到相同的异常。无论如何,我从 DoWork 例程中检查 invokerequired 对我来说没有任何意义,因为我的工作线程的重点是为我处理负载,而不是将其推回 UI 线程。

任何人都可以推荐一个解决方法,我可以尝试在这里实现我所追求的目标吗?

我的代码:

选择后的树视图连接到显示文件

 AddHandler TreeView.AfterSelect, AddressOf displayfile

 Private Sub displayfile(sender As Object, e As TreeViewEventArgs)
    Try

        Dim selectedfile As FileInfo = New FileInfo(e.Node.Tag) 'tag has our full path embedded.

        'todo: Future - consider type of the file and load a pre-made panel with appropriate host object
        If selectedfile.Extension.ToLower.Equals(".pdf") Then
            'show "loading...."
            LoadingPanel.BringToFront()
            backgroundworker.RunWorkerAsync(selectedfile.FullName)
        End If

    Catch ex As Exception

    End Try
End Sub

后台工作人员资料:

#Region "Background Worker Events"
' This event handler is where the time-consuming work is done. 
Private Sub backgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles backgroundworker.DoWork
    Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
    e.Result = LoadPDFInBackground(e.Argument)
End Sub

' This event handler updates the progress. 
Private Sub backgroundWorker_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles backgroundworker.ProgressChanged
    ProgressBar.Value = e.ProgressPercentage
End Sub

' This event handler deals with the results of the background operation. 
Private Sub backgroundWorker_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As RunWorkerCompletedEventArgs) Handles backgroundworker.RunWorkerCompleted
    If e.Result Then
        'hide loading panel and show pdf panel
        pdfviewer.BringToFront()
    Else
        'what to do if failed to load???
    End If
End Sub
#End Region

  Private Function LoadPDFInBackground(ByVal selectedfile As String) As Boolean
    Try
        pdfviewer.src = selectedfile
        Return True
    Catch ex As Exception
        Return False
    End Try
End Function

【问题讨论】:

  • 您能否说明错误发生在哪一行?
  • @FraserOfSmeg:我在堆栈跟踪中看到的唯一行 # 是 81。该行是上面的“pdfviewer.src = selectedfile”行。

标签: vb.net multithreading pdf worker-thread


【解决方案1】:

只是一个想法,但尝试更改此行:

pdfviewer.src = selectedfile

到以下:

If pdfviewer.InvokeRequired Then
    pdfviewer.Invoke(Sub() pdfviewer.src = selectedfile)

它可能会解决该错误。看看是不是很有趣。

【讨论】:

  • 嗯,这行得通。我想知道为什么关闭 control.checkforillegalcrossthreadcalls 没有效果,但这个有效果?通过调用调用,我实际上是跳转到 ui 线程上下文还是只是抓住句柄?我不做太多多线程的事情,所以在幕后我真的不知道它在做什么。
  • 不幸的是,这确实将处理交给了 UI(我认为)。解决此问题的唯一方法是在工作线程上创建 pdfveiwer 对象,这意味着每次加载新的 pdf 时都重新创建该对象。
  • 您可以简单地通过计时代码来检查它是否将其退回。试一试秒表类。
  • 我在调用启动工作线程之后直接对标签进行了更新,它一直等到整个 pdf 加载后才更新标签。所以看起来它完全跳到了 UI 线程。我想我将不得不找到一个支持流对象的 pdf 控件,因为我可以很容易地从工作线程中填充/返回其中一个。感谢您的帮助 FraserOfSmeg
  • 顺便说一句,尝试从工作线程实例化并返回 pdf com 对象,但它抛出异常,因为它必须在单线程单元类型线程上运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-30
相关资源
最近更新 更多