2017-07-04 2 views
0

Dieser Code behandelt hier nicht die Ausnahme, wenn keine Verbindung zum Server hergestellt werden kann. Irgendwelche Ideen warum? Vielen Dank!C# async - Ausnahme nicht behandelt

+3

'await' werden alle Ausnahme in Aggregate wickeln - Sie für die erste fangen sollte und dann prüfen,' aggregateException.InnerExceptions' Sammlung für die tatsächliche Ausnahme, die Fehler verursacht – Fabio

+0

Selbst wenn ich alle Ausnahmen fangen es –

+3

* nicht behandelt wird Sie nicht * Verwenden Sie 'async void'. Es kann nicht erwartet werden und alle von ihm verursachten Ausnahmen können nicht behandelt werden. Es ist nur für Event-Handler gedacht. –

Antwort

1

Die Sache ist: "async void" ist ein sehr gefährliches Konstrukt, das fast nie in Ihrem Produktionscode erscheinen sollte. Die Async-Methode ist keine interne Liste von Anweisungen, sondern eine Art Zustandsmaschine, die von einer "Warte" -Aussage auf eine andere umschaltet und verschiedene Dinge dazwischen ausführt, während sie "wartet". Sobald Sie eine Exception in dieser Statusmaschine ausgelöst haben, benötigen Sie einen speziellen Kontext, um die Stack-Trace usw. beizubehalten. Void-Methoden bieten keinen solchen Kontext. Aufgabe oder Aufgabe zurückgeben <etwas> stattdessen.

Als weitere Lesung, konnte ich Phil Haack sehr schön Blogpost empfehlen: http://haacked.com/archive/2014/11/11/async-void-methods/

1

verschiedene Probleme mit diesem Code Es gibt keine. Zunächst ist die Verwendung von async void nur für Ereignishandler vorgesehen. Eine async void-Methode kann nicht erwartet werden, und Ausnahmen, die sie auslöst, können nicht behandelt werden. Zweitens fälscht Task.Factory.StartNew(()=>client.Connect(host,port)) asynchrone Ausführung. Es blockiert immer noch einen Thread. Asynchrone Ausführung bedeutet, dass der Thread nicht blockiert ist, während auf den Abschluss des Vorgangs gewartet wird.

Ich nehme an, Sie verwenden TcpClient. Diese Klasse verfügt bereits über eine Methode ConnectAsync, die auf asynchrone Weise verbindet. Sie könnten Ihren Code dies vereinfachen:

private async Task StartClient() 
{ 
    try 
    { 
     await client.ConnectAsync(host,port); 
    } 
    catch (Exception exc) 
    { 
     MessageBox.Show(exc.ToString()); 
    } 
} 

Wenn Sie den Client in Reaktion auf eine UI-Ereignis, zum Beispiel eine Schaltfläche klicken starten wollen, dann würden Sie schreiben:

async void Button1_Click(object sender, EventArgs e) 
{ 
    await StartClient(); 
} 

oder

async void Button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     await StartClient(); 
     //Work with the client 
    } 
    catch(Exception exc) 
    { 
     MessageBox.Show(exc.ToString()); 
    } 
} 

Verwenden Sie abschließend eine Protokollierungsbibliothek anstelle von MessageBox.Show, z. B. log4net, damit Sie aufgrund von Threading-Problemen keine Ausnahmebedingungen verlieren.

+0

Danke für Ihre Antwort. Nein, ich benutze TcpClient nicht, ich benutze eine externe Lib, die Client - Server - Kommunikation behandelt. Selbst wenn ich den Rückgabetyp von StartClient zu Task ändern, funktioniert es nicht (alles andere wie in meinem ursprünglichen Post) –

+0

@ azmd108 Zuerst funktionieren Ausnahmen. Hast du das Debuggen versucht? Haben Sie in der 'catch'-Anweisung einen Haltepunkt gesetzt? Sind Sie sicher, dass * es * eine Ausnahme gibt? Wenn die Ausführung nicht in den Ausnahmebehandler eintritt, liegt dies daran, dass keine Ausnahme behandelt werden muss. Wenn Sie diese 'async void'-Methode dagegen von einer Konsolenanwendung aufrufen, wird die Anwendung möglicherweise beendet, bevor die Methode ausgeführt werden kann. –

+0

Es springt nicht in die Catch-Anweisung - das ist mein Problem - es fängt nicht an. Ja, es gibt eine System.Net.Sockets.SocketException geworfen –

Verwandte Themen