【问题标题】:Exception handling to Implement Socket timeout using TPL FromAsync使用 TPL FromAsync 实现套接字超时的异常处理
【发布时间】:2013-08-03 01:49:12
【问题描述】:

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

如果您看一下下面的代码,您会意识到我正在尝试这样做:等待 20 毫秒(此时已硬编码),如果可以建立连接,则调用 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 语句包装调用,但它可以有多个调用者,并且在每个调用者看起来都错误时这样做。

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

【问题讨论】:

    标签: c# exception .net-4.0 task-parallel-library


    【解决方案1】:

    我找到了一种方法来实现我正在寻找的东西:

    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。

    【讨论】:

    • 为什么是default(ISyncResult) 而不是null
    • 因为我喜欢它,而且有时我不必知道它是值类型还是引用类型。您认为有充分的理由将其替换为 null,@Matt?
    • 它只是让它读起来很奇怪,因为在这种情况下它总是评估为null。我(个人)只会在它实际上可以评估为不同的东西时使用它(即当涉及泛型时)
    猜你喜欢
    • 1970-01-01
    • 2013-07-13
    • 2012-04-10
    • 1970-01-01
    • 2012-02-01
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多