Async network operations never finish

async-await, c#, cancellation-token, idisposable, networking

Solution

So i've made an extension method on `IDisposable` that creates a `CancellationToken` that disposes the connection on timeout, so the task finishes and everything carries on:

public static IDisposable CreateTimeoutScope(this IDisposable disposable, TimeSpan timeSpan)
{
    var cancellationTokenSource = new CancellationTokenSource(timeSpan);
    var cancellationTokenRegistration = cancellationTokenSource.Token.Register(disposable.Dispose);
    return new DisposableScope(
        () =>
        {
            cancellationTokenRegistration.Dispose();
            cancellationTokenSource.Dispose();
            disposable.Dispose();
        });
}

And the usage is extremely simple:

try
{
    var client = new UdpClient();
    using (client.CreateTimeoutScope(TimeSpan.FromSeconds(2)))
    {
        var result = await client.ReceiveAsync();
        // Handle result
    }
}
catch (ObjectDisposedException)
{
    return null;
}

Extra Info:

public sealed class DisposableScope : IDisposable
{
    private readonly Action _closeScopeAction;
    public DisposableScope(Action closeScopeAction)
    {
        _closeScopeAction = closeScopeAction;
    }
    public void Dispose()
    {
        _closeScopeAction();
    }
}

Problem

I have several asynchronous network operations that return a task that may never finish: - `UdpClient.ReceiveAsync` doesn't accept a `CancellationToken` - `TcpClient.GetStream` returns a `NetworkStream` that doesn't respect the `CancellationToken` on `Stream.ReadAsync` (checking for cancellation only at the start of the operation) Both wait for a message that may never come (because of packet loss or no response for example). That means I have phantom tasks that never complete, continuations that will never run and used sockets on hold. I know i can use `TimeoutAfter`, but that will only fix the continuation problem. So what am I supposed to do?

Original source