diff --git a/CryptoExchange.Net/CryptoExchange.Net.xml b/CryptoExchange.Net/CryptoExchange.Net.xml
index eb0f4f6..e8565c6 100644
--- a/CryptoExchange.Net/CryptoExchange.Net.xml
+++ b/CryptoExchange.Net/CryptoExchange.Net.xml
@@ -3036,7 +3036,7 @@
-
+
@@ -3609,6 +3609,11 @@
Connection lost event
+
+
+ Connection closed and no reconnect is happening
+
+
Connecting restored event
@@ -3809,6 +3814,12 @@
Event when the connection is lost. The socket will automatically reconnect when possible.
+
+
+ Event when the connection is closed. This event happens when reconnecting/resubscribing has failed too often based on the and options,
+ or is false
+
+
Event when the connection is restored. Timespan parameter indicates the time the socket has been offline for before reconnecting.
diff --git a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs
index f3661b2..db12bca 100644
--- a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs
+++ b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs
@@ -247,11 +247,16 @@ namespace CryptoExchange.Net.OrderBook
subscription = startResult.Data;
subscription.ConnectionLost += () =>
{
-
log.Write(LogLevel.Warning, $"{Id} order book {Symbol} connection lost");
Status = OrderBookStatus.Reconnecting;
Reset();
};
+ subscription.ConnectionClosed += () =>
+ {
+ log.Write(LogLevel.Warning, $"{Id} order book {Symbol} disconnected");
+ Status = OrderBookStatus.Disconnected;
+ StopAsync();
+ };
subscription.ConnectionRestored += async time => await ResyncAsync().ConfigureAwait(false);
Status = OrderBookStatus.Synced;
@@ -336,6 +341,7 @@ namespace CryptoExchange.Net.OrderBook
if(subscription != null)
await subscription.CloseAsync().ConfigureAwait(false);
+ log.Write(LogLevel.Debug, $"{Id} order book {Symbol} stopped");
}
///
diff --git a/CryptoExchange.Net/SocketClient.cs b/CryptoExchange.Net/SocketClient.cs
index dc7f270..ba9683f 100644
--- a/CryptoExchange.Net/SocketClient.cs
+++ b/CryptoExchange.Net/SocketClient.cs
@@ -53,7 +53,7 @@ namespace CryptoExchange.Net
public int? MaxReconnectTries { get; protected set; }
///
public int? MaxResubscribeTries { get; protected set; }
- ///
+ ///
public int MaxConcurrentResubscriptionsPerSocket { get; protected set; }
///
/// Delegate used for processing byte data received from socket connections before it is processed by handlers
diff --git a/CryptoExchange.Net/Sockets/SocketConnection.cs b/CryptoExchange.Net/Sockets/SocketConnection.cs
index ea44585..4d66804 100644
--- a/CryptoExchange.Net/Sockets/SocketConnection.cs
+++ b/CryptoExchange.Net/Sockets/SocketConnection.cs
@@ -23,6 +23,10 @@ namespace CryptoExchange.Net.Sockets
///
public event Action? ConnectionLost;
///
+ /// Connection closed and no reconnect is happening
+ ///
+ public event Action? ConnectionClosed;
+ ///
/// Connecting restored event
///
public event Action? ConnectionRestored;
@@ -127,17 +131,6 @@ namespace CryptoExchange.Net.Sockets
Socket.Timeout = client.SocketNoDataTimeout;
Socket.OnMessage += ProcessMessage;
- Socket.OnClose += () =>
- {
- if (lostTriggered)
- return;
-
- DisconnectTime = DateTime.UtcNow;
- lostTriggered = true;
-
- if (ShouldReconnect)
- ConnectionLost?.Invoke();
- };
Socket.OnClose += SocketOnClose;
Socket.OnOpen += () =>
{
@@ -315,6 +308,13 @@ namespace CryptoExchange.Net.Sockets
if (Socket.Reconnecting)
return; // Already reconnecting
+ DisconnectTime = DateTime.UtcNow;
+ if (!lostTriggered)
+ {
+ lostTriggered = true;
+ ConnectionLost?.Invoke();
+ }
+
Socket.Reconnecting = true;
log.Write(LogLevel.Information, $"Socket {Socket.Id} Connection lost, will try to reconnect after {socketClient.ReconnectInterval}");
@@ -345,6 +345,7 @@ namespace CryptoExchange.Net.Sockets
socketClient.sockets.TryRemove(Socket.Id, out _);
Closed?.Invoke();
+ _ = Task.Run(() => ConnectionClosed?.Invoke());
break;
}
@@ -373,6 +374,7 @@ namespace CryptoExchange.Net.Sockets
socketClient.sockets.TryRemove(Socket.Id, out _);
Closed?.Invoke();
+ _ = Task.Run(() => ConnectionClosed?.Invoke());
}
else
log.Write(LogLevel.Debug, $"Socket {Socket.Id} resubscribing all subscriptions failed on reconnected socket{(socketClient.MaxResubscribeTries != null ? $", try {ResubscribeTry}/{socketClient.MaxResubscribeTries}" : "")}. Disconnecting and reconnecting.");
@@ -397,6 +399,9 @@ namespace CryptoExchange.Net.Sockets
}
else
{
+ if (!socketClient.AutoReconnect && ShouldReconnect)
+ _ = Task.Run(() => ConnectionClosed?.Invoke());
+
// No reconnecting needed
log.Write(LogLevel.Information, $"Socket {Socket.Id} closed");
if (socketClient.sockets.ContainsKey(Socket.Id))
diff --git a/CryptoExchange.Net/Sockets/UpdateSubscription.cs b/CryptoExchange.Net/Sockets/UpdateSubscription.cs
index 0d352ab..b3143ef 100644
--- a/CryptoExchange.Net/Sockets/UpdateSubscription.cs
+++ b/CryptoExchange.Net/Sockets/UpdateSubscription.cs
@@ -21,6 +21,16 @@ namespace CryptoExchange.Net.Sockets
remove => connection.ConnectionLost -= value;
}
+ ///
+ /// Event when the connection is closed. This event happens when reconnecting/resubscribing has failed too often based on the and options,
+ /// or is false
+ ///
+ public event Action ConnectionClosed
+ {
+ add => connection.ConnectionClosed += value;
+ remove => connection.ConnectionClosed -= value;
+ }
+
///
/// Event when the connection is restored. Timespan parameter indicates the time the socket has been offline for before reconnecting.
/// Note that when the executing code is suspended and resumed at a later period (for example laptop going to sleep) the disconnect time will be incorrect as the diconnect