2011-04-06 16 views
15

Tengo un botón en una hoja de Excel que inicia un nuevo subproceso para hacer algo de procesamiento. Si deseo hacer algún cambio en Excel (por ejemplo, escribir datos en una celda usando Worksheet.Range("A1").Value = "info";), creo que debo usar el hilo de la interfaz de usuario principal.VSTO: invocación en el subproceso principal de Excel

¿Cómo se puede hacer esto?

Típicamente en Winforms que yo llamaría Invoke en un control, pero los Excel.Application o Worksheet o Range objetos no tienen un método Invoke.

Respuesta

22

Ese trabajo no "necesita" hacerse en el hilo de la interfaz de usuario, .net coordinará la llamada por usted, pero si realiza llamadas repetidas desde un hilo de fondo puede que tenga problemas de rendimiento.

Pero para responder a su pregunta en concreto, si usted tiene .NET 3.5, en su complemento en caso de carga añadir lo siguiente:

_dispatcher = Dispatcher.CurrentDispatcher; 

y luego añadir:

public Dispatcher Dispatcher { get {return _dispatcher;} } 

A continuación, puede enviar al hilo de la interfaz de usuario al ir

Globals.ThisAdd.Dispatcher.Invoke(()=>{/*stuff*/}); 

Si no tiene .net 3.5, entonces hay algunos otros hilos synchronisa técnicas de sincronización, como usar SynchronizationContext.Current en lugar del Dispatcher.

+0

Gran respuesta. He estado golpeando mi cabeza en una pared por algo similar (xll add-in) y esto lo solucionó. Si bien el trabajo no "necesita" hacerse en el hilo de la interfaz de usuario como dices, si lo haces en otro hilo, probablemente encontrarás que Excel.exe todavía está dando vueltas en el Administrador de tareas después de cerrar la aplicación. –

+3

Para cualquier otra persona confundida con 'Dispatcher', debe agregar una referencia a' WindowBase' para acceder a la clase 'Dispatcher'. – dotNET

+0

El problema que tuve al invocar desde un hilo diferente fue que Excel a menudo estaba ocupado y lanzó una COMException. Esto lo resolvió. – Laurent

2

¿Ha intentado arrancar un BackgroundWorker desde su botón? Esto hace que sea muy fácil ya que los eventos ProgressChanged y RunWorkerCompleted se activarán en el hilo principal.

No he intentado esto en un entorno de Excel/VSTO, pero no veo por qué no funcionaría.

6

Esta es mi solución para un complemento VSTO que usa WindowsForms. No necesita ningún System.Windows.Forms.Control de usarlo:


inicialización en ThisAddIn clase:

añadir esta línea a la función "ThisAddIn_Startup":

this.TheWindowsFormsSynchronizationContext = WindowsFormsSynchronizationContext.Current 
              ?? new WindowsFormsSynchronizationContext(); 

Añadir esta nueva propiedad:

public SynchronizationContext TheWindowsFormsSynchronizationContext { get; private set; } 

A continuación, el uso en el subproceso de trabajo es:

 Globals.ThisAddIn.TheWindowsFormsSynchronizationContext.Send(d => 
     { 
      MyMethodToInvoke(); 
     }, null); 

Una segunda solución (no probado): Se podría tal vez también utilizar:

 var invokerControl = new Control(); 
     invokerControl.CreateControl(); //Forces the control handle to be created 
     invokerControl.Invoke(new MethodInvoker(MyMethodToInvoke)); 

Espero que ayude, Jörg

+0

¡Muchas gracias! ¡Después de buscar durante media hora, esta fue la única solución de trabajo para VSTO! – Pali

Cuestiones relacionadas