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?