Printing the content of a DocumentViewer in a different UI thread

二次信任 提交于 2019-11-29 04:43:52
Ross

After some more Googling, I stumbled across the following thread, which seems to be the exact issue I am having.

PrintDialog and a secondary UI thread severe problem

In that thread, the guy eventually uses a custom PrintDialog class (the source code of which is found here), which is much the same as built-in PrintDialog, but with a few tweaks to fix these cross-thread bugs (and it also overrides the XPS Document Writer, which apparently ties itself even further into the application's main UI thread)

I copied and pasted the code for that custom PrintDialog (and renamed the class to ThreadSafePrintDialog), removed my Print button's CommandTarget, and instead use my own Print method:

private void Print_Executed(object sender, ExecutedRoutedEventArgs args) {
    var printDialog = new ThreadSafePrintDialog();
    if (!printDialog.ShowDialog(this)) return;

    printDialog.PrintDocument(DocumentViewer.Document.DocumentPaginator, "My Document");
}

Works perfectly.

Kevek

Your hunch is correct. You cannot access this object on the UI thread when it has been created by another thread.

I believe you have a few options:

  1. You could create this document on the UI thread, perhaps gather the information that you need in a background thread and then actually construct the object on the UI thread. It depends what your document creation entails. You could do something like:

    public void CreateDocument(T inputDataForDocumentCreation) {
      var uiDispatcher = Dispatcher.CurrentDispatcher;
      ThreadPool.QueueUserWorkItem(_ => {
        // Load and create document components with yourDataForDocumentCreation
    
         dispatcher.BeginInvoke(DispatcherPriority.Normal, () => {
         //Actually create the document (this will happen on the UI thread, so it may be accessed from the UI thread)
      });
      });
    }
    
  2. You could perhaps send this command to the thread that creates this other document? Hold on to this thread and do a thread.Invoke(printMethod)

  3. You could look into Freezable Objects. Look at the bottom of this page, heading "Creating Your Own Freezable Class". This would make your document thread-safe to access from a different thread than that which created it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!