Domanda

Duplica: Come catturare eccezioni un ThreadPool.QueueUserWorkItem


sto in fila più delegati su .NET ThreadPool per un gran numero di servizi remoti indipendente chiamate che si definiscono più database e altre risorse non in linea. Da Accodamento queste chiamate sul ThreadPool io possa eseguire contemporaneamente e minimizzare la latenza complessiva.

private void CompleteAndQueuePayLoads(IEnumerable<UsagePayload> payLoads)
{
    List<WaitHandle> waitHndls = new List<WaitHandle>();
    foreach (UsagePayload uPyLd in payLoads)
    {
        ManualResetEvent txEvnt = new ManualResetEvent(false);
        UsagePayload uPyLd1 = uPyLd ;
        ThreadPool.QueueUserWorkItem(
            delegate
                {
                    if (!uPyLd1 .IsComplete)
                        // IEEDAL.GetPayloadReadings is long running DB call
                        try { IEEDAL.GetPayloadReadings(uPyLd1 ); }
                        catch (IEEAccessException iX)
                        {
                            log.Write(log.Level.Error,
                                  "IEEWSDAL.CompleteAndQueuePayLoads " + 
                                   " Delegate Failed " +
                                  iX.Message, iX);
                            txEvnt.Set();
                            throw;  // this causes parent thread to crash!
                            // was going to try Thread.Abort next ...
                            // Thread.CurrentThread.Abort();
                        }
                    UsageCache.PersistPayload(uPyLd1 );
                    SavePayLoadToProcessQueueFolder(uPyLd1 );
                    txEvnt.Set();
                });
        waitHndls.Add(txEvnt);
    }
    util.WaitAll(waitHndls.ToArray()); //To waitone on > 64 waithandles
}

Ma deve essere maneggiato transazionale, cioè, l'uscita del filo genitore deve essere consentito solo a procedere se tutte le discussioni bambino hanno avuto successo l'intero lotto. Avevo codificato il filo bambino ad un'eccezione personalizzata quando non è riuscito, ma ho scoperto che questo fa sì che il thread genitore di crash, come queste eccezioni non possono essere "catturati" nel thread genitore ...

Ho letto circa l'UnHandledExceptionEvent gettare dal CLR quando questo accade, ma ho bisogno di "gestire" questa eccezione nel metodo in cui questi fili bambino sono messe in coda e generato, per controllare il trattamento immediatamente a valle sulla base del successo di teh threeads bambino ... Come posso fare per questo?

È stato utile?

Soluzione

Lo faccio molto nel mio progetto attuale. L'approccio che ho preso è stato quello di fare il mio proprio scheduler che prende il delegato, aggiunge alla mia coda e li esegue per gestire la sincronizzazione alla fine, ecc.

Il "trucco" che ho usato in questo caso è quello di non chiamare il delegato direttamente sul pool di thread, ma piuttosto chiamare un metodo nel mio scheduler che avvolge il delegato e gestisce l'eccezione più garbo. In questo modo, l'attuale chiamata metodo interno, viene sempre gestito in maniera appropriata (per me) modo.

Quando un'eccezione accade, il mio scheduler viene notificato e si ferma pianificazione di attività future (che è un bel bonus), ma si occupa anche di raccontare il chiamante che c'era una sola eccezione.

Altri suggerimenti

Se il filo non riesce, potrebbe segnare che almeno un guasto si è verificato all'interno di una variabile locale della funzione CompleteAndQueuePayLoads, e aggiungere eccezioni / guasti variabili da esaminare in seguito.

Si potrebbe esaminare le estensioni Parallel Library per 3,5. È possibile utilizzare Parallel.Invoke sul blocco di codice di fare esattamente quello che si sta tentando.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top