2015-05-02 7 views
5

Ho un servizio Windows che genera un insieme di attività figlio su thread separati e che dovrebbe terminare solo quando tutte queste attività sono state completate correttamente. Non so in anticipo quanto tempo ci vorrà per terminare un'attività dopo che è stato ricevuto un segnale di arresto. Durante OnStop(), attendo intervalli per quel segnale di stop e continuo a richiedere un tempo aggiuntivo per tutto il tempo che il sistema è disposto a concedergli.Che cos'è un sovraccarico sicuro per RequestAdditionalTime()?

Ecco la struttura di base:

class MyService : ServiceBase 
{ 
    private CancellationTokenSource stopAllActivities; 
    private CountdownEvent runningActivities; 

    protected override void OnStart(string[] args) 
    { 
     // ... start a set of activities that signal runningActivities 
     //  when they stop 
     // ... initialize runningActivities to the number of activities 
    } 

    protected override void OnStop() 
    { 
     stopAllActivities.Cancel(); 

     while (!runningActivities.Wait(10000)) 
     { 
      RequestAdditionalTime(15000); // NOTE: 5000 added for overhead 
     } 
    } 
} 

Solo quanto "spese generali" dovrei essere aggiunta nella chiamata RequestAdditionalTime? Sono preoccupato che le richieste siano cumulative, anziché basate sul momento in cui viene effettuata ogni chiamata RequestAdditionalTime. In questo caso, l'aggiunta di un sovraccarico potrebbe comportare la negazione della richiesta da parte del sistema perché è troppo lontano in futuro. Ma se non aggiungo alcun overhead, il mio servizio potrebbe essere interrotto prima che abbia la possibilità di richiedere il prossimo blocco di tempo aggiuntivo.

risposta

5

This post non era esattamente incoraggiante:

La documentazione MSDN non menziona questo, ma sembra che il valore specificato in RequestAdditionalTime non è in realtà il tempo ‘addizionale’. Invece, sostituisce il valore in ServicesPipeTimeout. Peggio ancora, qualsiasi valore superiore a due minuti (120000 millisecondi) viene ignorato, cioè limitato a due minuti.

Spero che non sia il caso, ma sto postando questo come una risposta nel peggiore dei casi.

UPDATE: L'autore di questo post è stato così gentile da inviare una risposta molto dettagliata al mio commento, che ho copiato qui di seguito.

Lars, la risposta breve è no.

Quello che vorrei dire è che ora mi rendo conto che i servizi di Windows dovrebbero essere progettati per avviare e terminare rapidamente l'elaborazione quando richiesto di farlo.

In qualità di sviluppatori, tendiamo a concentrarci sull'implementazione dell'elaborazione, quindi a impacchettarla e consegnarla come servizio di Windows.

Tuttavia, questo non è l'approccio corretto per la progettazione di Servizi Windows. I servizi devono essere in grado di rispondere rapidamente alle richieste di avvio e arresto non solo quando un amministratore effettua la richiesta dalla console dei servizi ma anche quando il sistema operativo richiede un avvio come parte della sua elaborazione di avvio o di un arresto perché si sta arrestando ,

Considerare cosa succede quando Windows è configurato per lo spegnimento quando un UPS segnala che l'alimentazione è fallita. Non è appropriato che il servizio risponda con "Ho bisogno di qualche minuto in più ...".

È possibile scrivere servizi che reagiscono rapidamente per interrompere le richieste anche quando implementano attività di elaborazione di lunga durata. Di solito un processo di lunga durata consisterà nell'elaborazione in batch dei dati e l'elaborazione dovrebbe verificare se è stata richiesta una fermata a livello della più piccola unità di lavoro che garantisce la coerenza dei dati.

Ad esempio, il primo servizio in cui ho trovato il timeout di interruzione era un problema legato all'elaborazione di una coda di notifiche su un server remoto.L'elaborazione ha recuperato una notifica dalla coda, chiamando un servizio Web per recuperare i dati relativi all'oggetto della notifica e quindi scrivendo un file di dati per l'elaborazione da un'altra applicazione.

Ho implementato l'elaborazione come una chiamata pilotata dal timer in un unico metodo. Una volta chiamato il metodo, esso non ritorna finché tutte le notifiche nella coda non sono state elaborate. Mi sono reso conto che si trattava di un errore per un servizio di Windows perché occasionalmente potrebbero esserci decine di migliaia di notifiche nella coda e l'elaborazione potrebbe richiedere diversi minuti.

Il metodo è in grado di elaborare 50 notifiche al secondo. Quindi, quello che avrei dovuto fare era implementare un controllo per vedere se era stato richiesto un arresto prima di elaborare ogni notifica. Ciò avrebbe consentito il ritorno del metodo quando ha completato l'elaborazione di una notifica, ma prima che abbia iniziato a elaborare la notifica successiva. Ciò avrebbe garantito che il servizio rispondesse rapidamente a una richiesta di arresto e che tutte le notifiche in sospeso rimanessero in coda per l'elaborazione al riavvio del servizio.

Problemi correlati