0

This code here is not handling the Exception thrown, when it cant connect to the Server. Any Ideas why? Thanks!

public Form1()
        {
            InitializeComponent();
            StartClient();

        }
async private Task StartClient()
{
    try
    {
        await ConnectToServerAsync();
    }
    catch (System.Net.Sockets.SocketException)
    {
        MesssageBox.Show("TEST");
    }
}

private Task ConnectToServerAsync()
{
    return Task.Factory.StartNew(() => client.Connect(host, port));
}
14
  • 3
    await will wrap all exception in AggregateException - you should catch for that first and then check aggregateException.InnerExceptions collection for actual exception which caused error Commented Jul 4, 2017 at 9:55
  • Even if I catch all Exceptions it gets not handled Commented Jul 4, 2017 at 9:57
  • 3
    Don't use async void. It can't be awaited and any exceptions it raises can't be handled. It's only meant for event handlers Commented Jul 4, 2017 at 9:57
  • 3
    Why are you calling Task.Factory.StartNew like this? Why not Task.Run? Even better, why don't you use the asynchronous version of Connect? TcpClient.ConnectAsync for example is a truly asynchronous method while Task.Run(()=>client.Connect()) just fakes it Commented Jul 4, 2017 at 10:01
  • 2
    @Fabio Task.Result throws an AggregateException, await throws the exception that occured Commented Jul 4, 2017 at 10:06

2 Answers 2

1

The thing is: "async void" is very dangerous construct that should almost never appear in your production code. Async method is not a list of statements internally, it's kind of state machine that switches from one "await" statement to another, doing various things in-between while "awaiting". So, once you got an exception raised inside that state machine, you need special context to preserve the stack trace etc. Void methods do not provide such a context. Return Task or Task<something> instead.

As a further reading, I could recommend Phil Haack's very nice blogpost: http://haacked.com/archive/2014/11/11/async-void-methods/

Sign up to request clarification or add additional context in comments.

Comments

1

There are various problems with this code. First, using async void is only meant for event handlers. An async void method can't be awaited and any exceptions it throws can't be handled. Second, Task.Factory.StartNew(()=>client.Connect(host,port)) fakes asynchronous execution. It still blocks a thread. Asynchronous execution means that no thread is blocked while waiting for the operation to complete.

I assume you use TcpClient. This class already has a ConnectAsync method that connects in an asynchronous manner. You could simplify your code to this:

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

If you want to start the client in response to a UI event, eg a button click, you'd write :

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

or

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

Finally, use a logging library instead of MessageBox.Show, eg log4net so you don't lose exception messages due to threading issues.

7 Comments

Thanks for your answer. No, I do not use TcpClient, I use an external lib which handles Client - Server - Communication. Even if I change the return type of StartClient to Task ,its not working (leaving everything else as it is in my initial Post)
@azmd108 First, exceptions do work. Did you try debugging? Did you set a breakpoint in the catch statement? Are you sure there is an exception to begin with? If execution doesn't enter the exception handler, it's because there is no exception to handle. On the other hand, if you call that async void method from a console application, the application may terminate before the method has a chance to run
Its not jumping inside the Catch-Statement - that is my Problem - its not catching. Yes, there is a System.Net.Sockets.SocketException thrown
@azmd108 post actual code that reproduces the problem then. Who calls StartClient? Do you await for it to complete? What happens if you replace client.Connect with a throw new Exception() ?
Found out that if i execute the Compiled assembly, the catch block fires perfectly fine, only while debugging catch block is not triggered. Why is this?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.