En mi aplicación WPF, tengo Window
que contiene, entre otros controles, un DocumentViewer
.Imprimir el contenido de un DocumentViewer en un subproceso de interfaz de usuario diferente
Cuando esta ventana se abre y se carga, construye dinámicamente un FixedDocument
con un indicador de progreso, y luego lo muestra en el DocumentViewer
. Funciona, y para mejorar la experiencia del usuario, ejecuto esta ventana en su propio hilo, para que la ventana principal de la aplicación siga respondiendo mientras se está construyendo el documento.
Sobre la base de las puntas en this web page, abro la ventana en un nuevo hilo de esta manera:
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();
}
he sido feliz con esta configuración hasta ahora, pero me acabo de encontrar con un problema.
MyDocumentViewerWindow
contiene un botón de impresión, que hace referencia a la incorporada en el comando de impresión, dirigido a la DocumentViewer:
<Button Command="Print" CommandTarget="{Binding ElementName=MyDocumentViewer}">Print</Button>
Antes de que tuviera la ventana en su propio hilo, esto funcionó bien. Pero ahora, cuando hago clic en él, la aplicación falla. Visual Studio 2010 resalta la siguiente línea del código anterior como la ubicación del bloqueo, con el mensaje 'El hilo de llamada no puede acceder a este objeto porque lo posee un hilo diferente. ':
System.Windows.Threading.Dispatcher.Run();
El seguimiento de la pila comienza así:
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)
...
Mi impresión es que el diálogo de impresión se está abriendo en el hilo principal de interfaz de usuario, y tratando de acceder al documento que se crea, y de propiedad por mi propio hilo, de ahí el choque.
¿Alguna idea de cómo puedo solucionar esto? Me gustaría mantener la ventana en su propio hilo.
Gracias por eso. Crear mi documento implica crear instancias de FixedDocument, agregar objetos FixedPage, rellenarlos con controles, etc. Debido a que FixedDocument es un DispatcherObject, no pude crearlo en una cadena de fondo y luego configurarlo como fuente para DocumentViewer, ya que también creó una violación entre hilos. Descubrí que tengo que crear mi documento en el mismo hilo que mi DocumentViewer, es decir, en un hilo de interfaz de usuario :(Pero encontré una solución a mi problema, la publicaré ahora. – Ross