在我的WPF應用程序中,我特別有Window
,其中包含DocumentViewer
以及其他控件。在不同的UI線程中打印DocumentViewer的內容
打開並加載此窗口時,它會動態構建帶有進度指示器的FixedDocument
,然後將其顯示在DocumentViewer
中。它可以工作,爲了改善用戶體驗,我在自己的線程中運行此窗口,以便在構建文檔時主應用程序窗口仍然可以響應。
根據在this web page的提示,我在這樣一個新的線程打開我的窗口:
public void ShowDocumentViewerWindow(params object[] data) {
var thread = new Thread(() => {
var window = new MyDocumentViewerWindow(new MyObject(data));
window.Closed += (s, a) => window.Dispatcher.InvokeShutdown();
window.Show();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
我已經滿意這個設置,到目前爲止,但我只是遇到了一個問題。
MyDocumentViewerWindow
包含打印按鈕,它引用內置的打印命令,定位於中的DocumentViewer:
<Button Command="Print" CommandTarget="{Binding ElementName=MyDocumentViewer}">Print</Button>
之前,我曾在自己的線程窗口,這工作得很好。但是現在,當我點擊它時,應用程序崩潰。 Visual Studio 2010將以上代碼中的以下代碼行突出顯示爲崩潰位置,消息爲'調用線程不能訪問此對象,因爲不同的線程擁有它。「:
System.Windows.Threading.Dispatcher.Run();
堆棧跟蹤開始是這樣的:
at System.Windows.Threading.Dispatcher.VerifyAccess()
at MS.Internal.Printing.Win32PrintDialog.ShowDialog()
at System.Windows.Controls.PrintDialog.ShowDialog()
at System.Printing.PrintQueue.GatherDataFromPrintDialog(PrintDialog printDialog, XpsDocumentWriter&amp; writer, PrintTicket&amp; partialTrustPrintTicket, PrintQueue&amp; partialTrustPrintQueue, Double&amp; width, Double&amp; height, String jobDescription)
at System.Printing.PrintQueue.CreateXpsDocumentWriter(String jobDescription, PrintDocumentImageableArea&amp; documentImageableArea)
at System.Windows.Controls.Primitives.DocumentViewerBase.OnPrintCommand()
at System.Windows.Controls.Primitives.DocumentViewerBase.ExecutedRoutedEventHandler(Object target, ExecutedRoutedEventArgs args)
...
我的預感是,在打印對話框打開主UI線程,並試圖訪問所創建的文件和被佔用由我自己的線程,因此崩潰。
任何想法我可以解決這個問題?我想保持窗口在自己的線程中。
謝謝你。創建我的文檔包括實例化一個FixedDocument,添加FixedPage對象,用控件填充它們等等。由於FixedDocument是一個DispatcherObject,我無法在後臺線程中創建它,然後將其設置爲DocumentViewer的源,因爲這樣做也會創建跨線程違規。我發現我必須在與我的DocumentViewer相同的線程中創建我的文檔 - 即在UI線程上:-(但我只是找到解決方法來解決我的問題 - 我現在將其發佈。 – Ross