Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.AggregateException on Socket.EndAccept with TaskFactory.FromAsync

I am working with async operations with sockets (.Net 4 - VS 2010 SP1) and all seems to be working okay. However, after write and run an automated test, it pass green but displays an exception message:

---- UNHANDLED EXCEPTION ----
Thread Name: <No Name>
System.AggregateException: A Task's exception(s) were not observed either by Waiting on  the Task or accessing its Exception property. As a result, the unobserved exception was    rethrown by the finalizer thread. ---> System.ObjectDisposedException: Cannot access a    disposed object.
Object name: 'System.Net.Sockets.Socket'.
    at System.Net.Sockets.Socket.EndAccept(IAsyncResult asyncResult)
    at P2PNet.Listener.<ListenForConnections>b__0(IAsyncResult r) in  C:\Users\lucas.ontivero\Documents\Visual Studio  2010\Projects\P2PNet\P2PNet\Listener.cs:line 76
    at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2  endMethod, TaskCompletionSource`1 tcs)
    --- End of inner exception stack trace ---
    at System.Threading.Tasks.TaskExceptionHolder.Finalize()
---> (Inner Exception #0) System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
    at System.Net.Sockets.Socket.EndAccept(IAsyncResult asyncResult)
    at P2PNet.Listener.<ListenForConnections>b__0(IAsyncResult r) in   C:\Users\lucas.ontivero\Documents\Visual Studio    2010\Projects\P2PNet\P2PNet\Listener.cs:line 76
    at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endMethod, TaskCompletionSource`1 tcs)<---  

I know what that exception means, it means the socket was closed before the EndAccept method was called. I have no problems with that, what I really don´t know is how to prevent that exception in an elegant way. This is my code:

    private void ListenForConnections()
    {
        try
        {
            Task.Factory.FromAsync<Socket>(_listener.BeginAccept, _listener.EndAccept, _listener)
                .ContinueWith(task =>
                    {
                        if (task.IsFaulted) return;
                        ListenForConnections();

                        var newSocket = task.Result;
                        RaiseClientConnectedEvent(new ConnectionEventArgs(newSocket));
                    }, TaskContinuationOptions.OnlyOnRanToCompletion);
        }
        catch (ObjectDisposedException)
        {
        }

I´ve tried with the line:

if (task.IsFaulted) return; 

and also with:

.ContinueWith(task=>{}, TaskContinuation.OnlyOnFault);

But the exception is thrown anyway. Which is the way to prevent the exception?

Thank you!

like image 544
lontivero Avatar asked Mar 14 '26 13:03

lontivero


1 Answers

Your line:

if (task.IsFaulted) return; 

Is returning not faulted because you are checking the continuation task's status, not the preceding task. Change it to this:

    private void ListenForConnections() {
        Task<Socket> listentask = Task.Factory.FromAsync<Socket>(_listener.BeginAccept, _listener.EndAccept, _listener);
        listentask.ContinueWith(task => {
            if (listentask.IsFaulted) {
                //observe exception
                Exception exception = listentask.Exception;
                return;
            }
            ListenForConnections();

            var newSocket = listentask.Result;
            RaiseClientConnectedEvent(new ConnectionEventArgs(newSocket));
        });
        //don't forget to start it
        listentask.Start();
    }
like image 153
Nick Whaley Avatar answered Mar 17 '26 03:03

Nick Whaley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!