@@ -38,6 +38,12 @@ public class WebSocket
38
38
/// </summary>
39
39
public SocketState State => socket . State ;
40
40
41
+ /// <summary>
42
+ /// Wether to throw an exception or fail silently when acting on a closed WebSocket.
43
+ /// Defaults to <c>true</c>.
44
+ /// </summary>
45
+ public bool ThrowIfClosed { get ; set ; } = true ;
46
+
41
47
/// <summary>
42
48
/// The number of messages that are currently in the incoming queue.
43
49
/// These messages can be retreived without delay using the <see cref="Receive"/> and <see cref="ReceiveAsync"/> methods.
@@ -84,15 +90,15 @@ public event EventHandler? OnConnected
84
90
/// Queues a message to be sent to the peer.
85
91
/// This method will return immediately.
86
92
/// If the WebSocket is currently connecting, the message will be queued and sent once the WebSocket is connected.
87
- /// If the WebSocket is currently closing, the message will be discarded silently.
93
+ /// If the WebSocket is currently closing or closed , the message will be discarded silently.
88
94
/// </summary>
89
95
/// <remarks>
90
96
/// This method is thread-safe.
91
97
/// </remarks>
92
- /// <exception cref="InvalidOperationException">The WebSocket is closed.</exception>
98
+ /// <exception cref="InvalidOperationException">The WebSocket is closed and <see cref="ThrowIfClosed"/> == <c>true</c> .</exception>
93
99
public void Send ( Message message )
94
100
{
95
- ThrowIfClosed ( ) ;
101
+ if ( HandleClosed ( ) ) return ;
96
102
socket . SendRange ( FramesFromMessage ( message ) ) ;
97
103
}
98
104
@@ -116,12 +122,12 @@ public void Send(Message message)
116
122
/// Queues a message to be sent to the peer.
117
123
/// This Task will complete immediately.
118
124
/// If the WebSocket is currently connecting, the message will be queued and sent once the WebSocket is connected.
119
- /// If the WebSocket is currently closing, the message will be discarded silently.
125
+ /// If the WebSocket is currently closing or closed , the message will be discarded silently.
120
126
/// </summary>
121
- /// <exception cref="InvalidOperationException">The WebSocket is closed.</exception>
127
+ /// <exception cref="InvalidOperationException">The WebSocket is closed and <see cref="ThrowIfClosed"/> == <c>true</c> .</exception>
122
128
public async Task SendAsync ( Message message )
123
129
{
124
- ThrowIfClosed ( ) ;
130
+ if ( HandleClosed ( ) ) return ;
125
131
await socket . SendRangeAsync ( FramesFromMessage ( message ) ) ;
126
132
}
127
133
@@ -145,49 +151,55 @@ public async Task SendAsync(Message message)
145
151
/// Return the next message from the peer.
146
152
/// This method will block until a message is received.
147
153
/// </summary>
154
+ /// <remarks>
155
+ /// This method is not affected by <see cref="ThrowIfClosed"/> and will always throw if called in closed state.
156
+ /// </remarks>
148
157
/// <exception cref="InvalidOperationException">The WebSocket is closed.</exception>
149
158
/// <exception cref="OperationCanceledException">The WebSocket is being closed and thus this function could never return.</exception>
150
159
/// <exception cref="OperationCanceledException">The operation has been canceled using the given token.</exception>
151
160
public Message Receive ( CancellationToken token = default )
152
161
{
153
- ThrowIfClosed ( ) ;
162
+ if ( State == SocketState . Closed ) throw new InvalidOperationException ( "The WebSocket is closed." ) ;
154
163
return incoming . Dequeue ( token ) ;
155
164
}
156
165
157
166
/// <summary>
158
167
/// Return the next message from the peer.
159
168
/// This Task will complete successfully once a message has been received.
160
169
/// </summary>
170
+ /// <remarks>
171
+ /// This method is not affected by <see cref="ThrowIfClosed"/> and will always throw if called in closed state.
172
+ /// </remarks>
161
173
/// <exception cref="InvalidOperationException">The WebSocket is closed.</exception>
162
174
/// <exception cref="OperationCanceledException">The WebSocket is being closed and thus this function could never return.</exception>
163
175
/// <exception cref="OperationCanceledException">The operation has been canceled using the given token.</exception>
164
176
public async Task < Message > ReceiveAsync ( CancellationToken token = default )
165
177
{
166
- ThrowIfClosed ( ) ;
178
+ if ( State == SocketState . Closed ) throw new InvalidOperationException ( "The WebSocket is closed." ) ;
167
179
return await incoming . DequeueAsync ( token ) ;
168
180
}
169
181
170
182
/// <summary>
171
183
/// Try to receive a message from the peer.
172
184
/// This method will return immediately.
173
185
/// </summary>
174
- /// <returns>The next message from the peer, or <c>null</c> if there were no messages or the WebSocket is being closed.</returns>
175
- /// <exception cref="InvalidOperationException">The WebSocket is closed.</exception>
186
+ /// <returns>The next message from the peer, or <c>null</c> if there were no messages or the WebSocket is closing or closed.</returns>
187
+ /// <exception cref="InvalidOperationException">The WebSocket is closed and <see cref="ThrowIfClosed"/> == <c>true</c> .</exception>
176
188
public Message ? TryReceive ( )
177
189
{
178
- ThrowIfClosed ( ) ;
190
+ if ( HandleClosed ( ) ) return null ;
179
191
return incoming . TryDequeue ( ) ;
180
192
}
181
193
182
194
/// <summary>
183
195
/// Try to receive a message from the peer.
184
196
/// This Task will complete immediately.
185
197
/// </summary>
186
- /// <returns>The next message from the peer, or <c>null</c> if there were no messages or the WebSocket is being closed.</returns>
187
- /// <exception cref="InvalidOperationException">The WebSocket is closed.</exception>
198
+ /// <returns>The next message from the peer, or <c>null</c> if there were no messages or the WebSocket is closing or closed.</returns>
199
+ /// <exception cref="InvalidOperationException">The WebSocket is closed and <see cref="ThrowIfClosed"/> == <c>true</c> .</exception>
188
200
public async Task < Message ? > TryReceiveAsync ( )
189
201
{
190
- ThrowIfClosed ( ) ;
202
+ if ( HandleClosed ( ) ) return null ;
191
203
return await incoming . TryDequeueAsync ( ) ;
192
204
}
193
205
@@ -262,9 +274,6 @@ private Message MessageFromFrames(Queue<Frame> queue)
262
274
return message ;
263
275
}
264
276
265
- private void ThrowIfClosed ( )
266
- {
267
- if ( State == SocketState . Closed )
268
- throw new InvalidOperationException ( "The WebSocket is closed." ) ;
269
- }
277
+ private bool HandleClosed ( ) => State == SocketState . Closed &&
278
+ ( ThrowIfClosed ? throw new InvalidOperationException ( "The WebSocket is closed." ) : true ) ;
270
279
}
0 commit comments