2012-03-02 21 views
5

Estoy trabajando en ese tipo de subproceso de cola de acción y me gustaría esperar a que se realice una determinada acción. Me gustaría crear la acción en el hilo principal, luego pasarla a la función de hilo de la cola (hasta el final de la cola) y esperar a que se realice esta acción. Entonces necesito distinguir la acción que acabo de realizar y esperarla.¿Es seguro pasar el evento del hilo principal al hilo de trabajo y esperarlo?

He una (pseudo) siguiente código y me gustaría saber

  • es trabajar con sucesos de Windows hilo objeto segura?
  • En caso afirmativo, ¿este concepto sería eficiente?

type 
    TMyThread = class(TThread); 
    private 
    FEvent: THandle; 
    protected 
    procedure Execute; override; 
    public 
    procedure DoSomething(const AEvent: THandle); 
    end; 

procedure TMyThread.Execute; 
begin 
    // is it working with events thread safe ? 
    SetEvent(FEvent); 
    // the thread will continue, so I can't use WaitFor 
    // but it won't set this specific FEvent handle again 
    // I'm working on such kind of an action queue, so once the action with ID, 
    // here represented by the FEvent will be processed, it's removed from 
    // the action queue 
end; 

procedure TMyThread.DoSomething(const AEvent: THandle); 
begin 
    FEvent := AEvent; 
end; 

// here's roughly what I want to do 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    OnceUsedEvent: THandle; 
begin 
    // the thread is already running and it's instantiated in MyThread 
    // here I'm creating the event for the single request I need to be performed 
    // by the worker thread 
    OnceUsedEvent := CreateEvent(nil, True, False, nil); 
    try 
    // here I'm passing the event handle to the worker thread (like a kind of 
    // a request ID) 
    MyThread.DoSomething(OnceUsedEvent); 
    // and here I want to wait for 10 seconds (and also interrupt this waiting 
    // when the user closes the application if possible ?) for the thread if 
    // performs my request 
    WaitForSingleObject(OnceUsedEvent, 10000); 
    finally 
    // close the event handle 
    CloseHandle(OnceUsedEvent); 
    end; 
    // and continue with something else 
end; 

Gracias!

+0

Esperando en el evento en el botón controlador de eventos se bloqueará el hilo principal, por lo que no es lo que quieres! Tal vez pueda usar un evento en su lugar (que se invoca siempre que termine el hilo) – jpfollenius

+2

Esa espera no hará lo que usted desee. No puede ser interrumpido. ¿Y por qué querrías bloquear por 10 segundos? Eso es simplemente extraño. –

+0

Idealmente INFINITO; Y es para cambiar el nombre de acción. Necesito ingresar al modo de edición del nodo VirtualTreeView y mantener vivo el editor hasta que obtenga el resultado de la acción de cambio de nombre del hilo (tengo un controlador de eventos adicional donde necesito pasar el resultado si el cambio tuvo éxito y cuando salgo este controlador de eventos el editor está oculto). –

Respuesta

4

Sí, eso está perfectamente bien. El identificador devuelto por CreateEvent puede ser utilizado libremente por todos los hilos. Cualquier otra cosa lo haría bastante inútil ya que este es su uso principal :)

+1

No necesariamente. Me parece plausible que un identificador pueda ser específico de subprocesos, o al menos no intrínsecamente seguro para subprocesos. Si otro hilo quería acceso al mismo evento, podría ser que necesita llamar a DuplicateHandle, o necesita llamar a CreateEvent con el mismo nombre de evento. –

+0

Empíricamente, el asa se puede usar desde otros subprocesos: he usado eventos de esa manera a menudo. –

+0

@RobKennedy eso es exactamente lo que siempre he hecho hasta hoy cuando vi un ejemplo de que alguien acaba de tener ambos hilos usando la misma variable de control ... –

3

No espere los hilos en los controladores de eventos GUI. No lo haga esperando eventos, semáforos o mutexes, bucles sleep(), bucles DoEvents o cualquier combinación de los mismos.

Si desea comunicarse con el hilo principal para indicar que algo se ha procesado en un threadpool, mire la API PostMessage().

+0

Alternativas al uso de 'PostMessage' cuando se comunica con la banda de rodadura principal son 1)' Thread .Queue' como se describe aquí [synchronize-and-queue-with-parameters] (http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/#more-135) (esto es útil para aplicaciones FireMonkey) o 2) usando una 'cola segura para hilos 'y sondeando la cola del hilo principal con un ciclo de temporizador. –

+0

'synchronize-and-queue-with-parameters' es OK-ish, pero hace dos llamadas al sistema solo para descubrir en qué hilo se está ejecutando :(Usar un temporizador para sondear está bien para mostrar periódicamente las actualizaciones más recientes el valor de fecha de muchas variables, pero solo introduce la latencia si se usa para sondear una cola. –

Cuestiones relacionadas