我有几个异步网络操作,它们返回的任务可能永远不会完成:
UdpClient.ReceiveAsync
CancellationToken
TcpClient.GetStream
NetworkStream
Stream.ReadAsync
两者都等待 可能 永远不会出现的消息(例如,由于丢包或无响应)。这意味着我有无法完成的 幻像 任务,将永远不会运行的继续操作以及已使用的套接字处于保留状态。我知道我可以使用TimeoutAfter,但这只会解决继续问题。
TimeoutAfter
那我该怎么办?
因此,我在其上IDisposable创建了一个扩展方法,该方法创建了一个CancellationToken在超时时处理连接的方法,因此任务完成,一切都继续进行:
IDisposable
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(); }); }
而且用法非常简单:
try { var client = new UdpClient(); using (client.CreateTimeoutScope(TimeSpan.FromSeconds(2))) { var result = await client.ReceiveAsync(); // Handle result } } catch (ObjectDisposedException) { return null; }
额外信息:
public sealed class DisposableScope : IDisposable { private readonly Action _closeScopeAction; public DisposableScope(Action closeScopeAction) { _closeScopeAction = closeScopeAction; } public void Dispose() { _closeScopeAction(); } }