异步网络运营写不完 [英] Async network operations never finish

查看:181
本文介绍了异步网络运营写不完的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个异步网络操作返回可能永远不会完成一个任务:

I have several asynchronous network operations that return a task that may never finish:


  1. UdpClient.ReceiveAsync 不接受的CancellationToken

  2. TcpClient.GetStream 返回的NetworkStream 不尊重的CancellationToken Stream.ReadAsync (只在操作开始检查取消)

  1. UdpClient.ReceiveAsync doesn't accept a CancellationToken
  2. TcpClient.GetStream returns a NetworkStream that doesn't respect the CancellationToken on Stream.ReadAsync (checking for cancellation only at the start of the operation)

这两个等待的消息可以从来没有(因为数据包丢失或如无反应)来了。这意味着我的幻影的任务永远不会完成,这将永远不会运行,并保持使用的插座延续。我知道我可以使用 TimeoutAfter ,但只会修复的延续问题。

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.

那我该怎么办?

推荐答案

所以我做了一个扩展方法上的的IDisposable 创建一个的CancellationToken 是部署在超时的连接,所以任务完成,一切都进行:

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();
        });
}

和用法极其简单:

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();
    }
}

这篇关于异步网络运营写不完的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆