I recently talked about .NET WebSocket Libraries, and how I like using WebSocket4Net as a .NET WebSocket client. That library is great, but really wanted it to have two additional features:
- Retry logic for opening a connection.
- An OpenAsync method.
...so I created an extension method that does both!
WebSocket4Net Extensions
public static class WebSocketExtensions
{
public static async Task OpenAsync(
this WebSocket webSocket,
int retryCount = 5,
CancellationToken cancelToken = default(CancellationToken))
{
var failCount = 0;
var exceptions = new List<Exception>(retryCount);
var openCompletionSource = new TaskCompletionSource<bool>();
cancelToken.Register(() => openCompletionSource.TrySetCanceled());
EventHandler openHandler = (s, e) => openCompletionSource.TrySetResult(true);
EventHandler<ErrorEventArgs> errorHandler = (s, e) =>
{
if (exceptions.All(ex => ex.Message != e.Exception.Message))
{
exceptions.Add(e.Exception);
}
};
EventHandler closeHandler = (s, e) =>
{
if (cancelToken.IsCancellationRequested)
{
openCompletionSource.TrySetCanceled();
}
else if (++failCount < retryCount)
{
webSocket.Open();
}
else
{
var exception = exceptions.Count == 1
? exceptions.Single()
: new AggregateException(exceptions);
var webSocketException = new WebSocketException(
"Unable to connect",
exception);
openCompletionSource.TrySetException(webSocketException);
}
};
try
{
webSocket.Opened += openHandler;
webSocket.Error += errorHandler;
webSocket.Closed += closeHandler;
webSocket.Open();
await openCompletionSource.Task.ConfigureAwait(false);
}
finally
{
webSocket.Opened -= openHandler;
webSocket.Error -= errorHandler;
webSocket.Closed -= closeHandler;
}
}
Enjoy,
Tom
No comments:
Post a Comment