diff --git a/ElectronNET.API/App.cs b/ElectronNET.API/App.cs
index 6717e63..935a619 100644
--- a/ElectronNET.API/App.cs
+++ b/ElectronNET.API/App.cs
@@ -25,6 +25,24 @@ namespace ElectronNET.API
///
public static bool SocketDebug { get; set; }
+ ///
+ /// Handle hard fails of connecting to the socket. The application must exit when this event is raised.
+ /// The default behavior is to exit with code 0xDEAD
+ ///
+ public static event Action OnSocketConnectFail;
+
+ internal static bool TryRaiseOnSocketConnectFail()
+ {
+ if (OnSocketConnectFail is object)
+ {
+ OnSocketConnectFail();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
///
/// Emitted when the user clicks on the dock on Mac
diff --git a/ElectronNET.API/BridgeConnector.cs b/ElectronNET.API/BridgeConnector.cs
index a2f1bb3..50ca7d2 100644
--- a/ElectronNET.API/BridgeConnector.cs
+++ b/ElectronNET.API/BridgeConnector.cs
@@ -93,7 +93,6 @@ namespace ElectronNET.API
private static readonly SemaphoreSlim _socketSemaphoreHandlers = new(1, 1);
private static AsyncManualResetEvent _connectedSocketEvent = new AsyncManualResetEvent();
- private static TaskCompletionSource _connectedSocketTask = new();
private static Dictionary> _eventHandlers = new ();
@@ -109,7 +108,7 @@ namespace ElectronNET.API
private static async Task GetSocket()
{
await _connectedSocketEvent.WaitAsync();
- return await _connectedSocketTask.Task;
+ return _socket;
}
public static bool IsConnected => _waitForConnection is Task task && task.IsCompletedSuccessfully;
@@ -435,84 +434,46 @@ namespace ElectronNET.API
var socket = new SocketIO($"http://localhost:{BridgeSettings.SocketPort}", new SocketIOOptions()
{
EIO = 3,
- Reconnection = false,
+ Reconnection = true,
ReconnectionAttempts = int.MaxValue,
- ReconnectionDelay = 1000,
+ ReconnectionDelay = 500,
ReconnectionDelayMax = 5000,
RandomizationFactor = 0.5,
ConnectionTimeout = TimeSpan.FromSeconds(10)
});
socket.JsonSerializer = new CamelCaseNewtonsoftJsonSerializer();
+
+ _connectedSocketEvent.Reset();
socket.OnConnected += (_, __) =>
{
- if (_socket == socket)
- {
- _connectedSocketTask.TrySetResult(socket);
- _connectedSocketEvent.Set();
- Log("ElectronNET socket {1} connected on port {0}!", BridgeSettings.SocketPort, socket.Id);
- }
+ _connectedSocketEvent.Set();
+ Log("ElectronNET socket {1} connected on port {0}!", BridgeSettings.SocketPort, socket.Id);
};
socket.OnReconnectAttempt += (_, __) =>
{
- if (_socket == socket)
- {
- _connectedSocketEvent.Reset();
- _connectedSocketTask = new();
- Log("ElectronNET socket {1} is trying to reconnect on port {0}...", BridgeSettings.SocketPort, socket.Id);
- }
+ _connectedSocketEvent.Reset();
+ Log("ElectronNET socket {1} is trying to reconnect on port {0}...", BridgeSettings.SocketPort, socket.Id);
};
socket.OnReconnectError += (_, ex) =>
{
- if (_socket == socket)
- {
- Log("ElectronNET socket {1} failed to connect {0}", ex, socket.Id);
- _connectedSocketEvent.Reset();
- _connectedSocketTask = new();
- _socket = null;
- }
+ _connectedSocketEvent.Reset();
+ Log("ElectronNET socket {1} failed to connect {0}", ex, socket.Id);
};
socket.OnReconnected += (_, __) =>
{
- if (_socket == socket)
- {
- _connectedSocketTask.TrySetResult(socket);
- _connectedSocketEvent.Set();
- Log("ElectronNET socket {1} reconnected on port {0}...", BridgeSettings.SocketPort, socket.Id);
- }
+ _connectedSocketEvent.Set();
+ Log("ElectronNET socket {1} reconnected on port {0}...", BridgeSettings.SocketPort, socket.Id);
};
socket.OnDisconnected += (_, reason) =>
{
- if (_socket == socket)
- {
- _connectedSocketEvent.Reset();
- _connectedSocketTask = new();
- _socket = null;
-
- Task.Run(async () =>
- {
- await Task.Yield();
- EnsureSocketTaskIsCreated();
- });
-
- Log("ElectronNET socket {2} disconnected with reason {0}, trying to reconnect on port {1}!", reason, BridgeSettings.SocketPort, socket.Id);
- }
- else
- {
- try
- {
- socket.Dispose();
- }
- catch
- {
- //Ignore
- }
- }
+ _connectedSocketEvent.Reset();
+ Log("ElectronNET socket {2} disconnected with reason {0}, trying to reconnect on port {1}!", reason, BridgeSettings.SocketPort, socket.Id);
};
_socket = socket;
@@ -521,23 +482,15 @@ namespace ElectronNET.API
{
try
{
- if (!socket.Connected)
- {
- if (_socket == socket)
- {
- await socket.ConnectAsync();
- _connectedSocketTask.TrySetResult(socket);
- _connectedSocketEvent.Set();
- }
- }
- return;
+ await socket.ConnectAsync();
}
catch (Exception e)
{
- await Task.Delay(1000);
- if (!socket.Connected)
+ Console.WriteLine(e.ToString());
+
+ if(!App.TryRaiseOnSocketConnectFail())
{
- LogError(e, "Failed to connect");
+ Environment.Exit(0xDEAD);
}
}
});
@@ -548,26 +501,6 @@ namespace ElectronNET.API
{
throw new Exception("Missing Socket Port");
}
-
- if(_backgroundMonitorThread is null)
- {
- _backgroundMonitorThread = new Thread(() =>
- {
- while (true)
- {
- Thread.Sleep(5_000);
-
- if (HybridSupport.IsElectronActive)
- {
- EnsureSocketTaskIsCreated();
- }
- }
- });
- _backgroundMonitorThread.IsBackground = true;
- _backgroundMonitorThread.Name = "Monitor Electron Socket";
- _backgroundMonitorThread.Priority = ThreadPriority.Lowest;
- _backgroundMonitorThread.Start();
- }
}
}
else
diff --git a/ElectronNET.Host/main.js b/ElectronNET.Host/main.js
index b1a4e67..b0d3dfc 100644
--- a/ElectronNET.Host/main.js
+++ b/ElectronNET.Host/main.js
@@ -229,7 +229,7 @@ function startSocketApiBridge(port) {
server = require('http').createServer();
io = require('socket.io')();
- io.attach(server, { pingTimeout: 5000, pingInterval: 10000 });
+ io.attach(server, { pingTimeout: 10000, pingInterval: 5000 });
server.listen(port, 'localhost');
server.on('listening', function () {
@@ -263,50 +263,32 @@ function startSocketApiBridge(port) {
}
});
- let firstTime = (global['electronsocket'] === undefined);
+ //We only hook to events on app on the first initialization of each component
+ let firstTime = (global['electronsocket'] == undefined);
- if (firstTime) {
- console.log("First socket connection");
- global['electronsocket'] = socket;
- socket.setMaxListeners(0);
- }
+ global['electronsocket'] = socket;
+ socket.setMaxListeners(0);
console.log('.NET connected on socket ' + socket.id + ' on ' + new Date());
- if (appApi === undefined) appApi = require('./api/app')(socket, app, firstTime);
- if (browserWindows === undefined) browserWindows = require('./api/browserWindows')(socket, app, firstTime);
- if (commandLine === undefined) commandLine = require('./api/commandLine')(socket, app);
- if (autoUpdater === undefined) autoUpdater = require('./api/autoUpdater')(socket, app);
- if (ipc === undefined) ipc = require('./api/ipc')(socket);
- if (menu === undefined) menu = require('./api/menu')(socket);
- if (dialogApi === undefined) dialogApi = require('./api/dialog')(socket);
- if (notification === undefined) notification = require('./api/notification')(socket);
- if (tray === undefined) tray = require('./api/tray')(socket);
- if (webContents === undefined) webContents = require('./api/webContents')(socket);
- if (globalShortcut === undefined) globalShortcut = require('./api/globalShortcut')(socket);
- if (shellApi === undefined) shellApi = require('./api/shell')(socket);
- if (screen === undefined) screen = require('./api/screen')(socket);
- if (clipboard === undefined) clipboard = require('./api/clipboard')(socket);
- if (browserView === undefined) browserView = require('./api/browserView').browserViewApi(socket);
- if (powerMonitor === undefined) powerMonitor = require('./api/powerMonitor')(socket);
- if (nativeThemeApi === undefined) nativeThemeApi = require('./api/nativeTheme')(socket);
- if (dock === undefined) dock = require('./api/dock')(socket);
-
- socket.on('register-app-open-file-event', (id) => {
- global['electronsocket'] = socket;
-
- app.on('open-file', (event, file) => {
-
- if (global['electronsocket'] === socket) {
- event.preventDefault();
- global['electronsocket'].emit('app-open-file' + id, file);
- }
- });
-
- if (launchFile) {
- global['electronsocket'].emit('app-open-file' + id, launchFile);
- }
- });
+ appApi = require('./api/app')(socket, app, firstTime);
+ browserWindows = require('./api/browserWindows')(socket, app, firstTime);
+ commandLine = require('./api/commandLine')(socket, app);
+ autoUpdater = require('./api/autoUpdater')(socket, app);
+ ipc = require('./api/ipc')(socket);
+ menu = require('./api/menu')(socket);
+ dialogApi = require('./api/dialog')(socket);
+ notification = require('./api/notification')(socket);
+ tray = require('./api/tray')(socket);
+ webContents = require('./api/webContents')(socket);
+ globalShortcut = require('./api/globalShortcut')(socket);
+ shellApi = require('./api/shell')(socket);
+ screen = require('./api/screen')(socket);
+ clipboard = require('./api/clipboard')(socket);
+ browserView = require('./api/browserView').browserViewApi(socket);
+ powerMonitor = require('./api/powerMonitor')(socket);
+ nativeThemeApi = require('./api/nativeTheme')(socket);
+ dock = require('./api/dock')(socket);
socket.on('splashscreen-destroy', () => {
if (splashScreen) {
@@ -315,17 +297,29 @@ function startSocketApiBridge(port) {
}
});
+ socket.on('register-app-open-file-event', (id) => {
+ global['electronsocket'] = socket;
+
+ app.on('open-file', (event, file) => {
+ event.preventDefault();
+ global['electronsocket'].emit('app-open-file' + id, file);
+ });
+
+ if (launchFile) {
+ socket.emit('app-open-file' + id, launchFile);
+ }
+ });
+
socket.on('register-app-open-url-event', (id) => {
global['electronsocket'] = socket;
app.on('open-url', (event, url) => {
event.preventDefault();
-
global['electronsocket'].emit('app-open-url' + id, url);
});
if (launchUrl) {
- global['electronsocket'].emit('app-open-url' + id, launchUrl);
+ socket.emit('app-open-url' + id, launchUrl);
}
});
@@ -415,7 +409,7 @@ function startAspCoreBackend(electronPort) {
else if (os.platform() === 'darwin') {
//There is a bug on the updater on macOS never quiting and starting the update process
//We give Squirrel.Mac enough time to access the update file, and then just force-exit here
- setTimeout(() => app.exit(0), 10_000);
+ setTimeout(() => app.exit(0), 30_000);
}
});