2015-01-20 3 views
5

Der unten aufgeführte Aufruf MessageBox.Show zeigt "Inner". Ist das ein Fehler?Control.Invoke wickelt die äußere Ausnahme ab und propagiert stattdessen die innere Ausnahme

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

Ich bemerke, dass die 'aware Task.Run()' nicht relevant ist. Sie sollten es aus Ihrer Frage weglassen, da es nur dazu dient, von dem Problem abzulenken, nach dem Sie fragen. –

+0

Das ist interessant. Wenn wir noch eine weitere innere Ausnahme hinzufügen, wird es uns auch geben. – Chris

+0

Flaggers: Sorge dafür, die Frage tatsächlich zu lesen, bevor du sie als Duplikat von [diesem anderen] kennzeichnest (http://stackoverflow.com/questions/15704711/how-cani-i-use-control-invoke-to-trow-) eine Ausnahme, die nicht ignoriert wird? – Juan

Antwort

5

Ich hatte einen Blick auf die Referenzquelle für System.Windows.Forms.Control, und den Code, der mit Invoke beschäftigt sich wie folgt aussieht:

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; 
} 

So offensichtlich ist es so von Entwurf. Die Kommentare in der Quelle bieten keine Erklärung dafür, warum sie dies tun.

EDIT: Einige Website, die nun Ansprüche dieser Kommentar kam von einem Mann an Microsoft gegangen ist:

auf dem winform comfirmation im Datensatz Basierend, ist unsere Analyse korrekt von der Ursache und dieses Verhalten ist beabsichtigt. Der Grund war zu verhindern, dass der Benutzer zu viele interne Windows.Forms-Mechanismen sieht. Dies liegt daran, dass das Standardfehlerdialogfeld von Winform auch Application.ThreadException nutzt, um die Ausnahmedetails anzuzeigen. .Net Winform Team trimmt die anderen Ausnahmen Informationen, so dass der Standardfehler Dialog nicht alle Details für den Endbenutzer angezeigt werden.

Auch einige MSFTs haben vorgeschlagen, dieses Verhalten zu ändern. Allerdings .Net Winform-Team denkt, dass das Ändern der Ausnahme zu werfen ist eine brechende Änderung und aus diesem Grund wird WinForms weiterhin die innerste Ausnahme an den Application.ThreadException-Handler senden.

+1

Ich stelle fest, dass es zwei bereits bereinigte Connect-Berichte zum Thema gibt, zuvor unter http://connect.microsoft.com/VisualStudio/feedback/details/386582/control-invoke-exception-handling und http: // connect.microsoft.com/VisualStudio/feedbackdetail/view/433765/control-invoke-throws-exception-getbaseexception-rather-than-the-actual-exception (Wenn Sie versuchen, zu diesen Links zu gelangen, meldet die Website, dass die Seiten vorhanden sind weg oder verboten). Sie können jeweils kleine Snippets sehen, indem Sie MSDN mit "control.invoke inner exception" suchen und sich die Zusammenfassungen ansehen. –

+0

Schöne Ergebnisse. Konnte den Code in ILSPY jedoch nicht finden. – Juan

+1

@Juan Überprüfen Sie 'InvokeMarshaledCallbacks()' unter 'System.Windows.Forms.Control'. – Chris

Verwandte Themen