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

C# 使用TPL FromAsync实现套接字超时的异常处理,c#,exception,.net-4.0,task-parallel-library,C#,Exception,.net 4.0,Task Parallel Library,我正在开发一个应用程序,其中连接尝试超时应该是可配置的 如果你看一下下面的代码,你会意识到我正在尝试这样做:等待20毫秒(此时它是硬编码的),如果可以建立连接,那么用true调用onConnected回调操作;否则为false(例如,如果发生超时) 内部无效连接(操作未连接) { Func beginConnect= (回调,s)=> { var asyncResult=_socket.BeginConnect(端点,回调,s); var success=asyncResult.AsyncWai

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

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

内部无效连接(操作未连接)
{
Func beginConnect=
(回调,s)=>
{
var asyncResult=_socket.BeginConnect(端点,回调,s);
var success=asyncResult.AsyncWaitHandle.WaitOne(20,true);
如果(!success)抛出新的TimeoutException(“连接超时”);
返回结果;
};
var task=task.Factory.fromsync(beginConnect,_socket.EndConnect,this);
task.ContinueWith(t=>onConnected(true),TaskContinuationOptions.notonfault)
.ContinueWith(t=>onConnected(false),TaskContinuationOptions.OnlyOnFaulted);
task.ContinueWith(t=>onConnected(false),TaskContinuationOptions.OnlyOnFaulted);
}
问题是,由于beginConnect函数中存在超时异常,因此从未调用回调。我想我可以在Connect方法调用程序中,用一个tyrcatch语句包装调用,但是它可以有几个调用程序,并且在每个调用程序中都这样做看起来是错误的


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

我找到了一种实现我所追求的目标的方法:

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);
}
内部无效连接(操作未连接)
{
Func beginConnect=
(回调,s)=>
{
var asyncResult=_socket.BeginConnect(端点,回调,s);
var success=asyncResult.AsyncWaitHandle.WaitOne(20,true);
如果(!成功)
{
未连接(错误);
返回默认值(IAsyncResult);
}
返回结果;
};
var task=task.Factory.fromsync(beginConnect,_socket.EndConnect,this);
task.ContinueWith(t=>onConnected(true),TaskContinuationOptions.notonfault)
.ContinueWith(t=>onConnected(false),TaskContinuationOptions.OnlyOnFaulted);
task.ContinueWith(t=>onConnected(false),TaskContinuationOptions.OnlyOnFaulted);
}

关键是,20毫秒后,如果尚未连接,它将调用带有false的回调,并返回默认的IAsyncResult。

为什么
default(issyncResult)
而不是
null
?因为我喜欢它,有时我不必知道它是值还是引用类型。你认为用null替换它有什么好的理由吗,@Matt?这让它读起来很奇怪,因为在这种情况下,它的计算结果总是
null
。我(个人)只会在它能够实际计算出不同的结果时使用它(即,当涉及泛型时)
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);
}