使用TPL-FromAsync实现套接字超时的异常处理

本文关键字:异常处理 超时 套接字 TPL-FromAsync 实现 使用 | 更新日期: 2023-09-27 18:26:09

我正在开发一个应用程序,其中连接尝试超时应该是可配置的。

如果你看一下下面的代码,你会意识到我正在尝试:等待20毫秒(现在已经硬编码了),如果可以建立连接,那么用true调用onConnected回调操作;否则为false(例如,如果发生超时)

internal void Connect(Action<bool> onConnected)
{
    Func<AsyncCallback, object, IAsyncResult> beginConnect =
        (callback, s) =>
            {
                var asyncResult = _socket.BeginConnect(Endpoint, callback, s);
                var success = asyncResult.AsyncWaitHandle.WaitOne(20, true);
                if(!success) throw new TimeoutException("Connection timeout");
                return asyncResult;
            };
    var task = Task.Factory.FromAsync(beginConnect, _socket.EndConnect, this);
    task.ContinueWith(t => onConnected(true), TaskContinuationOptions.NotOnFaulted)
        .ContinueWith(t => onConnected(false), TaskContinuationOptions.OnlyOnFaulted);
    task.ContinueWith(t => onConnected(false), TaskContinuationOptions.OnlyOnFaulted);
}

问题是,由于beginConnect函数中的超时异常,回调从未被调用。我想我可以在Connect方法调用程序中,用tyr-catch语句包装调用,但它可以有多个调用程序,并且在每个调用程序中都这样做。

我怎样才能实现我想要的?

使用TPL-FromAsync实现套接字超时的异常处理

我找到了一种实现我想要的东西的方法:

internal void Connect(Action<bool> onConnected)
{
    Func<AsyncCallback, object, IAsyncResult> beginConnect =
        (callback, s) => 
            {
                var asyncResult = _socket.BeginConnect(Endpoint, callback, s);
                var success = asyncResult.AsyncWaitHandle.WaitOne(20, true);
                if(!success)
                {
                    onConnected(false);
                    return default(IAsyncResult);
                }
                return asyncResult;
            };
    var task = Task.Factory.FromAsync(beginConnect, _socket.EndConnect, this);
    task.ContinueWith(t => onConnected(true), TaskContinuationOptions.NotOnFaulted)
        .ContinueWith(t => onConnected(false), TaskContinuationOptions.OnlyOnFaulted);
    task.ContinueWith(t => onConnected(false), TaskContinuationOptions.OnlyOnFaulted);
}

关键是,20ms后,如果还没有连接,它会用false调用回调,并返回默认的IAsyncResult。