2009-07-19 37 views
13

En aras de la discusión, considere un subproceso de interfaz de usuario como un subproceso que ha recibido una llamada al Application.Run() o una de sus sobrecargas invocadas y tiene un bucle de mensaje activo ejecutándose.¿Cómo detectar si estamos en un hilo de interfaz de usuario?

¿Hay alguna manera de detectar si actualmente estamos ejecutando un hilo de este tipo?

La razón por la que quiero esto es porque tengo una clase con una función privada de larga ejecución. La clase en sí misma ya está multiproceso y el uso de esta clase es tal que se puede usar desde la IU o desde los hilos de fondo que están procesando. Esta función también cae en esta red. Pero no quiero que bloquee el hilo de UI. Así que quiero detectar si estoy ejecutando un subproceso de UI y, de ser así, mover la llamada de función a un hilo de fondo (probablemente ThreadPool, pero eso no es un problema para esta discusión). Esto se comporta completamente bien, pero los hilos de fondo probablemente dependen de la salida de la función, por lo que es mejor bloquearlos, mientras que el hilo de la interfaz de usuario está accediendo a ella de una manera más "configurada y olvidada".

Respuesta

7

Yo sugeriría que es el tipo de decisión de la persona que llama debe hacer. Siempre puedes escribir métodos de envoltura para hacerlo más fácil, pero significa que no tendrás problemas con la persona que llama estando en una situación "extraña" (por ejemplo, un marco de UI que no conoces, o alguna otra cosa con un bucle de evento)) y usted toma la decisión equivocada por ellos.

Si el método alguna vez necesita proporcionar retroalimentación en el hilo correcto, pasaría un ISynchronizeInvoke (implementado por Control) para hacer eso en una forma UI-agnóstica.

12

Si tiene acceso a Form o Control, puede marcar la propiedad InvokeRequired; esto devolverá false si está en el hilo de UI y true si no lo está ... Si ocurre en un contexto en el que no puede consultar con Control, puede configurar fácilmente una propiedad estática en su programa que pueda consultar. Almacenar una referencia a Thread.CurrentThread en el arranque, y para comparar Thread.CurrentThread a que se hace referencia cuando se necesita saber:

static class Program 
{ 
    private static Thread _startupThread = null; 

    [STAThread] 
    static void Main() 
    { 
     _startupThread = Thread.CurrentThread; 

     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1()); 
    } 

    public static bool IsRunningOnStartupThread() 
    { 
     return Thread.CurrentThread == _startupThread; 
    } 
} 

Llamando Program.IsRunningOnStartupThread obtendrá una bool decir si está o no.

+0

El hilo de inicio no es necesariamente el hilo de la GUI, o el único hilo de la GUI. –

+1

INCORRECTO: InvokeRequired devuelve verdadero si está en un "hilo diferente al que se creó el control" –

+1

@Rico: Sí, por supuesto. No puedo creer que el error tipográfico haya estado ahí durante los últimos tres años y que nadie se haya dado cuenta. Gracias por atraparlo, actualicé la respuesta en consecuencia. –

8

bool isMessageLoopThread = System.Windows.Forms.Application.MessageLoop;

+0

Esta es la respuesta más simple para mis propósitos. – ToolmakerSteve

Cuestiones relacionadas