Domanda

sto usando il TPL ( Task Parallel Biblioteca ) in .NET 4.0. Voglio centralizzare la logica la gestione di tutte le eccezioni non gestite utilizzando l'evento Thread.GetDomain().UnhandledException. Tuttavia, nella mia richiesta, l'evento non viene mai licenziato per le discussioni iniziate con il codice di TPL, per esempio Task.Factory.StartNew(...). L'evento è infatti licenziato se uso qualcosa di simile new Thread(threadStart).Start().

Questo MSDN articolo suggerisce di utilizzare Task.Wait () per catturare il AggregateException quando si lavora con TPL, ma non è quello che voglio, perché questo meccanismo non è "centralizzata" abbastanza.

Qualcuno esperienza lo stesso problema a tutti o è solo a me? Avete qualche soluzione per questo?

È stato utile?

Soluzione 2

Sembra che non c'è built-in modo per gestire questa (e nessuna risposta a questa domanda, dopo quasi 2 settimane). Ho già messo a punto un codice personalizzato per prendersi cura di questo. La descrizione soluzione è abbastanza lungo, quindi ho postato nel mio blog. Fare riferimento a questo post se siete interessati.

Aggiornamento 5/7/2010: Ho trovato un modo migliore per farlo, facendo uso di compito di continuazione. Creo un class ThreadFactory che espone l'evento di errore che può essere sottoscritto da un gestore di livello superiore e fornisce metodi per avviare un'attività collegata con una corretta continuazione.
Il codice è pubblicato qui .

Aggiornamento 2011/04/18:. CAP dal post sul blog come da commento di Nifle

internal class ThreadFactory
{
    public delegate void TaskError(Task task, Exception error);

    public static readonly ThreadFactory Instance = new ThreadFactory();

    private ThreadFactory() {}

    public event TaskError Error;

    public void InvokeError(Task task, Exception error)
    {
        TaskError handler = Error;
        if (handler != null) handler(task, error);
    }

    public void Start(Action action)
    {
        var task = new Task(action);
        Start(task);
    }

    public void Start(Action action, TaskCreationOptions options)
    {
        var task = new Task(action, options);
        Start(task);
    }

    private void Start(Task task)
    {
        task.ContinueWith(t => InvokeError(t, t.Exception.InnerException),
                            TaskContinuationOptions.OnlyOnFaulted |
                            TaskContinuationOptions.ExecuteSynchronously);
        task.Start();
    }
}

Altri suggerimenti

TaskScheduler.UnobservedTaskException Evento è quello che desiderare:

  

Si verifica quando un'eccezione non osservata una in errore della Task è in procinto di innesco   politica di escalation eccezione, che, per impostazione predefinita, chiuderebbe il   processo.

Quindi, questo evento è simile a DomainUnhandledException che lei ha citato nella sua domanda, ma si verifica solo per le attività.

A proposito nota, che la politica non osservabili-eccezioni (sì, questo non è un non osservabili eccezioni, ragazzi MS inventato nuova parola ... di nuovo), cambiato da .NET 4.0 per .NET 4.5. In .NET 4.0 non osservati eccezione porta a cessazione processo, ma in .NET 4.5 - non lo fanno. Questo è tutto a causa novità asincrona che avremo in C # 5 e VB 11.

Vedo due opzioni che possono essere utilizzati ai fini della centralizzazione della gestione delle eccezioni in TPL:   1. Utilizzando dei inosservato Task evento di eccezione di Utilità di pianificazione.   2. Utilizzo delle continuazioni per le attività con stato di errore.

Utilizzo del inosservato Task evento di eccezione di Utilità di pianificazione.

Il task scheduler ha un evento UnobservedTaskException a cui è possibile iscriversi utilizzando l'operatore + =.

  • Nota 1: Nel corpo del gestore è necessario fare la chiamata SetObserved () su argomenti UnobservedTaskExceptionEventArgs per notificare scheduler tale eccezione è stata gestita .
  • Nota 2:. Il gestore viene chiamato quando i compiti sono stati raccolti dal garbage collector
  • Nota 3:. Se si dovrà attendere il compito che sarà comunque costretto a protezione di attesa per blocco try / catch
  • Nota 4:. Il criterio predefinito per le eccezioni non gestite Task NET 4.0 e 4.5 è diverso

Sommario:. Questo approccio è buono per le attività fire-and-forget e per la cattura di eccezioni sfuggito dalla vostra politica la gestione delle eccezioni centralizzata

Utilizzo delle continuazioni per le attività con stato di errore.

Con TPL è possibile allegare azioni al compito utilizzando il metodo ContinueWith () che prende connessi opzione azione e la continuazione. Questa azione sarà chiamato dopo la cessazione delle attività e solo nei casi previsti dalla opzione. In particolare:

    t.ContinueWith(c => { /* exception handling code */ },
                   TaskContinuationOptions.OnlyOnFaulted);

installa continuazione con il codice gestione delle eccezioni al Task t. Questo codice viene eseguito solamente nel caso in cui t Task stato chiuso a causa l'eccezione non gestita.

  • Nota 1: Ottenere valore di eccezione nel codice di gestione eccezioni. Altrimenti sarà gorgogliare fuori.
  • Nota 2:. Codice di gestione delle eccezioni verrà chiamato immediatamente dopo la cessazione Task
  • Nota 3: Se l'eccezione è stato ottenuto nel codice di gestione delle eccezioni sarà considerato come gestito, prova / blocco catch sul compito di attesa non sarà in grado di prenderlo.

Penso che sarà meglio per centralizzata manipolazioni devono utilizzare i task personalizzati ereditati da Task con gestore di eccezioni aggiunto tramite la continuazione eccezione. E accompagnare questo approccio utilizzando dei inosservato Task evento di eccezione di Utilità di pianificazione per i tentativi di cattura da utilizzare compiti non personalizzate.

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