2012-03-13 8 views
5

Escribo una aplicación que debe hacer algunas cosas en segundo plano: revisar correos electrónicos y analizarlos para inyectar datos en una base de datos y conectarse a un servicio web para verificar el estado de algunos operaciones asincrónicas.Detectando poca actividad de usuario y revisando correo electrónico en segundo plano

En este momento, mi solución es un temporizador simple que realiza estas operaciones en un programa predefinido: correo electrónico cada cinco minutos y servicio web comprueba cada minuto (pero estos solo se realizan si hay actividad pendiente, por lo que la mayoría de las veces esto no hace nada.)

Ahora no estoy usando un hilo para esto (estoy en una etapa temprana de desarrollo). Pero mi plan es crear un hilo de fondo y dejarlo hacer el trabajo fuera de línea.

par de preguntas:

  1. tengo la intención de controlar todo en el temporizador (s). Configure una variable global ("bloqueo" rudimentario), inicie el hilo. Si el "bloqueo" ya está configurado, ignórelo. El hilo lo limpia en la terminación. ¿Debo usar un mecanismo de bloqueo/cola más robusto para mis hilos? (Ya tengo instalado OmniThread)
  2. ¿Cómo puedo ejecutar un hilo con baja prioridad? No quiero que la aplicación se sienta lenta cuando el hilo de fondo está realizando una inserción de datos o una red.
  3. ¿Existe alguna forma clara de verificar la actividad del usuario y comenzar esta secuencia solo cuando el usuario no está ocupado con el teclado/mouse?

Tenga en cuenta que no tengo experiencia con los hilos. Escribí una aplicación de sincronización de FTP una vez, así que no soy un completo novato, pero eso fue hace mucho tiempo.

+1

Esta es una aplicación que le permite crear/editar facturas, etc. Pero también necesita leer el correo electrónico y analizarlo para inyectar facturas electrónicas adjuntas como documentos recibidos, y conectarse a la oficina de impuestos para obtener el estado de las facturas enviadas . No quiero interrumpir al usuario para estas operaciones, así que quiero que se ejecuten en segundo plano. –

+1

Si su fondo no tiene una interacción directa con su aplicación, le sugiero que use un servicio por separado (puede configurarlo con baja prioridad si lo desea) para ejecutarlos. Entonces, esos trabajos pueden procesarse incluso si su aplicación está cerrada o incluso si ningún usuario inició sesión. – Justmade

+0

@Justmade - Sí quiero recibir una notificación cuando lleguen nuevos correos electrónicos (facturas). –

Respuesta

1
  1. tengo la intención de controlar todo en el temporizador (s). Configure una variable global ("bloqueo" rudimentario), inicie el hilo. Si el "bloqueo" ya está configurado, ignórelo. El hilo lo limpia en la terminación. ¿Debo usar un mecanismo de bloqueo/cola más robusto para mis hilos? (Ya tengo instalado OmniThread)

no me molestaría con el temporizador en absoluto.Haga que el lazo de su hilo se vea así, y tendrá sus retrasos. NO necesitará un candado porque solo hay un hilo, no dormirá hasta que el trabajo anterior haya terminado.

procedure YourThread; 
var N: Integer; 
begin 
    while not Terminated do 
    begin 
    // Figure out if there's a job to do 
    // Do the job 

    // Sleep for a while, but give the thread a chance to notice 
    // it needs to terminate. 
    for N := 1 to 500 do 
     if not Terminated then 
     Sleep(100); 
    end; 
end; 
  1. ¿Cómo puedo ejecutar un hilo de baja prioridad? No quiero que la aplicación se sienta lenta cuando el hilo de fondo está realizando una inserción de datos o una red.

Do not incomher. Puede usar fácilmente SetThreadPriority pero no vale la pena. Si su hilo de fondo está esperando E/S (red), entonces no consumirá ningún recurso de la CPU. Incluso si su hilo de fondo funciona a toda velocidad, su GUI no se sentirá lenta porque Windows hace un buen trabajo dividiendo el tiempo de CPU disponible entre todos los hilos disponibles.

  1. ¿Hay una manera limpia para verificar la actividad del usuario e iniciar este hilo sólo cuando el usuario no está ocupado en el teclado/ratón?

De nuevo, ¿por qué molestarse en comprobar la actividad del usuario? La comprobación del correo electrónico está vinculada a la red (es decir, E/S), la comprobación del hilo para el correo electrónico será en su mayoría esté inactivo.

+4

Dormir 50 segundos en un hilo es un poco excesivo. Recuerde que cuando llegue el momento de matar el hilo, la aplicación se bloqueará durante 50 segundos en el peor de los casos ... – whosrdaddy

+0

'Recuerde que cuando llegue el momento de matar el hilo, la aplicación se bloqueará durante 50 segundos en el peor caso '- no si el SO lo mata en la aplicación cercana. Si se espera que los subprocesos se ejecuten hasta que se cierre la aplicación, y no intente terminarlos explícitamente y esperarlos, no hay problema: la aplicación se cerrará sin demora. –

+0

de acuerdo, pero los hilos que siguen vivos después de la aplicación son malos :) – whosrdaddy

1

¿No puede hacer todo esto en el hilo de fondo, deshacerse de todo el micro-manejo de hilos? Me parece que podría simplemente recorrer una llamada de suspensión (60000) en el hilo de fondo. Compruebe el servicio web cada vez que pasa el ciclo, revise el correo electrónico cada 5 veces. Puede establecer la prioridad en tpLower, si lo desea, pero este hilo estará durmiendo o bloqueado en E/S casi todo el tiempo, por lo que no creo que valga la pena escribir.

Me sorprendería que dicho hilo sea perceptible para el usuario en el teclado/mouse, sin importar cuándo se ejecuta.

'Configure una variable global (' bloqueo 'rudimentario), comience el hilo' - ¿Qué pretende hacer esta variable global? ¿Qué hay para bloquear?

+0

No sé cuánto tiempo tardará en completarse este subproceso. Entonces, si el TTimer se establece en cinco minutos, la invocación anterior aún puede estar activa; es por eso que menciono alguna forma de bloqueo. –

+0

Como tener solo un hilo de fondo, dormir la mayor parte del tiempo puede funcionar. ¿Entonces dices que esto es barato? –

+0

@LeonardoHerrera - debería estar bien, sí. El uso de un bucle de suspensión mantiene el hilo principal "fuera de él"; el temporizador no es necesario. Si una actividad lleva más de cinco minutos, no importa; una actividad nueva no puede comenzar hasta cinco minutos después de que termine la última. Si este 'jiter' es inaceptable, no es difícil almacenar un TdateTime 'lastRun' para cuando se inició la última ejecución de la actividad. Un nuevo intervalo de suspensión() puede calcularse después de la actividad como 'trunc ((now-lastRun) * msecPerDay)'. NOTA: si este número es negativo, ¡no duerma nada, estará durmiendo durante mucho tiempo! –

6

Para la parte 3 de su pregunta, la API de Windows tiene una función GetLastInputInfo que debe devolver información sobre la última vez que el usuario hizo algo. Incluso dice que es "Esta función es útil para la detección de entrada inactiva". Planeé usar esto para algo yo mismo, pero no tuve la oportunidad de probarlo.

Editar: Delphi implementation link

+0

Funciona correctamente (se utiliza para invocar salvapantallas, tareas inactivas del programador de tareas, etc.) – OnTheFly

Cuestiones relacionadas