@@ -74,74 +74,77 @@ private void ConfigureConnectedSocket(Socket socket)
74
74
75
75
private void Connect ( Socket socket , EndPoint endPoint , CancellationToken cancellationToken )
76
76
{
77
- IAsyncResult asyncResult ;
78
- var dnsEndPoint = endPoint as DnsEndPoint ;
79
- if ( dnsEndPoint != null )
80
- {
81
- // mono doesn't support DnsEndPoint in its BeginConnect method.
82
- asyncResult = socket . BeginConnect ( dnsEndPoint . Host , dnsEndPoint . Port , null , null ) ;
83
- }
84
- else
85
- {
86
- asyncResult = socket . BeginConnect ( endPoint , null , null ) ;
87
- }
77
+ var cancelled = false ;
78
+ var timedOut = false ;
88
79
89
- asyncResult . AsyncWaitHandle . WaitOne ( _settings . ConnectTimeout ) ;
90
- if ( ! asyncResult . IsCompleted )
80
+ using ( var registration = cancellationToken . Register ( ( ) => { cancelled = true ; try { socket . Close ( ) ; } catch { } } ) )
81
+ using ( var timer = new Timer ( _ => { timedOut = true ; try { socket . Close ( ) ; } catch { } } , null , _settings . ConnectTimeout , Timeout . InfiniteTimeSpan ) )
91
82
{
92
83
try
93
84
{
94
- socket . Dispose ( ) ;
85
+ var dnsEndPoint = endPoint as DnsEndPoint ;
86
+ if ( dnsEndPoint != null )
87
+ {
88
+ // mono doesn't support DnsEndPoint in its BeginConnect method.
89
+ socket . Connect ( dnsEndPoint . Host , dnsEndPoint . Port ) ;
90
+ }
91
+ else
92
+ {
93
+ socket . Connect ( endPoint ) ;
94
+ }
95
95
}
96
96
catch
97
97
{
98
- // ignore exceptions
98
+ if ( ! cancelled && ! timedOut )
99
+ {
100
+ throw ;
101
+ }
99
102
}
103
+ }
100
104
105
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
106
+ if ( timedOut )
107
+ {
101
108
var message = string . Format ( "Timed out connecting to {0}. Timeout was {1}." , endPoint , _settings . ConnectTimeout ) ;
102
109
throw new TimeoutException ( message ) ;
103
110
}
104
-
105
- socket . EndConnect ( asyncResult ) ;
106
111
}
107
112
108
113
private async Task ConnectAsync ( Socket socket , EndPoint endPoint , CancellationToken cancellationToken )
109
114
{
110
- Task connectTask ;
111
- var dnsEndPoint = endPoint as DnsEndPoint ;
112
- if ( dnsEndPoint != null )
113
- {
114
- // mono doesn't support DnsEndPoint in its BeginConnect method.
115
- connectTask = Task . Factory . FromAsync ( socket . BeginConnect ( dnsEndPoint . Host , dnsEndPoint . Port , null , null ) , socket . EndConnect ) ;
116
- }
117
- else
118
- {
119
- connectTask = Task . Factory . FromAsync ( socket . BeginConnect ( endPoint , null , null ) , socket . EndConnect ) ;
120
- }
115
+ var cancelled = false ;
116
+ var timedOut = false ;
121
117
122
- if ( _settings . ConnectTimeout == Timeout . InfiniteTimeSpan )
118
+ using ( var registration = cancellationToken . Register ( ( ) => { cancelled = true ; try { socket . Close ( ) ; } catch { } } ) )
119
+ using ( var timer = new Timer ( _ => { timedOut = true ; try { socket . Close ( ) ; } catch { } } , null , _settings . ConnectTimeout , Timeout . InfiniteTimeSpan ) )
123
120
{
124
- await connectTask . ConfigureAwait ( false ) ;
125
- return ;
126
- }
127
-
128
- using ( var delayCancellationTokenSource = new CancellationTokenSource ( ) )
129
- {
130
- var delayTask = Task . Delay ( _settings . ConnectTimeout , delayCancellationTokenSource . Token ) ;
131
-
132
- var completedTask = await Task . WhenAny ( connectTask , delayTask ) . ConfigureAwait ( false ) ;
133
-
134
- // kill the delay timer as soon as possible
135
- delayCancellationTokenSource . Cancel ( ) ;
136
-
137
- if ( completedTask == delayTask && ! socket . Connected )
121
+ try
122
+ {
123
+ var dnsEndPoint = endPoint as DnsEndPoint ;
124
+ if ( dnsEndPoint != null )
125
+ {
126
+ // mono doesn't support DnsEndPoint in its BeginConnect method.
127
+ await Task . Factory . FromAsync ( socket . BeginConnect ( dnsEndPoint . Host , dnsEndPoint . Port , null , null ) , socket . EndConnect ) . ConfigureAwait ( false ) ;
128
+ }
129
+ else
130
+ {
131
+ await Task . Factory . FromAsync ( socket . BeginConnect ( endPoint , null , null ) , socket . EndConnect ) . ConfigureAwait ( false ) ;
132
+ }
133
+ }
134
+ catch
138
135
{
139
- socket . Dispose ( ) ;
140
- var message = string . Format ( "Timed out connecting to {0}. Timeout was {1}." , endPoint , _settings . ConnectTimeout ) ;
141
- throw new TimeoutException ( message ) ;
136
+ if ( ! cancelled && ! timedOut )
137
+ {
138
+ throw ;
139
+ }
142
140
}
141
+ }
143
142
144
- await connectTask . ConfigureAwait ( false ) ;
143
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
144
+ if ( timedOut )
145
+ {
146
+ var message = string . Format ( "Timed out connecting to {0}. Timeout was {1}." , endPoint , _settings . ConnectTimeout ) ;
147
+ throw new TimeoutException ( message ) ;
145
148
}
146
149
}
147
150
0 commit comments