2015-01-20 13 views
5

Il MessageBox.Show richiamo sottostante mostra "interno". è un insetto?Control.Invoke scarta l'eccezione esterno e propaga l'eccezione interna invece

private void Throw() 
{ 
    Invoke(new Action(() => 
    { 
     throw new Exception("Outer", new Exception("Inner")); 
    })); 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     Throw(); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); // Shows "Inner" 
    } 
} 
+1

rilevo che il 'attendere Task.Run()' non è rilevante. Dovresti ometterlo dalla tua domanda, in quanto serve solo a distrarre dal problema che stai chiedendo. –

+0

Questo è interessante. Se aggiungiamo un'altra eccezione interiore, ci darà anche quella. Segnalatori – Chris

+0

: attenzione a leggere effettivamente la domanda prima di contrassegnarla come duplicato di [questo altro] (http://stackoverflow.com/questions/15704711/how-can-i-use-control-invoke-to-throw- un-eccezioni-that-wont-be-ignorati)? – Juan

risposta

5

ho dato un'occhiata alla fonte di riferimento per System.Windows.Forms.Control, e il codice che si occupa di Invoke assomiglia a questo:

try { 
    InvokeMarshaledCallback(current); 
} 
catch (Exception t) { 
    current.exception = t.GetBaseException(); 
} 

GetBaseException:

public virtual Exception GetBaseException() 
{ 
    Exception inner = InnerException; 
    Exception back = this; 

    while (inner != null) { 
     back = inner; 
     inner = inner.InnerException; 
    } 

    return back; 
} 

Quindi a quanto pare è come questo dal design. I commenti nella fonte non offrono alcuna spiegazione sul motivo per cui lo fanno.

EDIT: Alcuni sito che è ormai andato pretese questo commento è venuto da un ragazzo al Microsoft:

Sulla base del comfirmation winform nel record, la nostra analisi è corretta la causa principale e questo comportamento è previsto. Il motivo era di impedire all'utente di vedere troppo dei meccanismi interni di Windows.Forms. Questo perché la finestra di dialogo degli errori predefinita del winform sfrutta anche Application.ThreadException per mostrare i dettagli delle eccezioni. . Net Winform squadra taglia le altre informazioni sulle eccezioni in modo che la finestra di dialogo di errore predefinita non visualizzi tutti i dettagli all'utente finale.

Inoltre, alcuni hanno MSFTs sugguested a cambiare questo comportamento. Tuttavia, .Net squadra Winform pensa che cambiando l'eccezione di gettare una rottura cambiamento e per questo motivo WinForms continuerà ad inviare l'eccezione più interna al gestore Application.ThreadException.

+1

faccio notare che ci sono anche due ora-epurati Collegare riporta sul tema, in precedenza presso gli URL http://connect.microsoft.com/VisualStudio/feedback/details/386582/control-invoke-exception-handling e http: // connect.microsoft.com/VisualStudio/feedbackdetail/view/433765/control-invoke-throws-exception-getbaseexception-rather-than-the-actual-exception (se si tenta di accedere a tali collegamenti, il sito Web riporta che le pagine sono andato o proibito). Puoi vedere piccoli frammenti di ciascuno cercando MSDN con "eccezione interna control.invoke" e guardando i riepiloghi. –

+0

Belle scoperte. Non ho trovato il codice in ILSPY. – Juan

+1

@Juan Controlla 'InvokeMarshaledCallbacks()' in 'System.Windows.Forms.Control'. – Chris