/// <summary> /// Runs the receive / reconnect life cycle asynchronously. /// </summary> /// <returns>a task that represents the asynchronous operation</returns> /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception> private async Task RunLifeCycleAsync() { EnsureNotDisposed(); while (!_cancellationTokenSource !.IsCancellationRequested) { // receive new payload until the web-socket is connected. while (IsConnected && !_cancellationTokenSource.IsCancellationRequested) { await ProcessNextPayload(); } var lostConnectionAt = DateTimeOffset.UtcNow; // try reconnect for (var attempt = 1; !_cancellationTokenSource.IsCancellationRequested; attempt++) { // reconnect await ConnectAsync(); if (IsConnected) { // reconnection successful break; } var eventArgs = new ReconnectAttemptEventArgs(_webSocketUri, attempt, _reconnectionStrategy); await OnReconnectAttemptAsync(eventArgs); // give up if (eventArgs.CancelReconnect) { Logger?.Log(this, "Reconnection aborted due event."); return; } // add delay between reconnects var delay = _reconnectionStrategy(lostConnectionAt, attempt); // reconnection give up if (delay is null) { Logger?.Log(this, "Reconnection failed! .. giving up.", LogLevel.Warning); return; } Logger?.Log(this, string.Format("Waiting {0} before next reconnect attempt...", delay.Value), LogLevel.Debug); await Task.Delay(delay.Value); } } }
/// <summary> /// Triggers the <see cref="ReconnectAttempt"/> event asynchronously. /// </summary> /// <param name="eventArgs">the event arguments</param> /// <returns>a task that represents the asynchronously operation.</returns> protected virtual Task OnReconnectAttemptAsync(ReconnectAttemptEventArgs eventArgs) => ReconnectAttempt.InvokeAsync(this, eventArgs);