/// <summary> /// Use heartbeat to keep the REST API listening after initialization, /// be sure to call from a thread and not the main thread /// </summary> void DoHeartbeat() { bool reconnect = false; if (null == _sApiChromaInstance) { //LogErrorOnMainThread("DoHeartbeat: ApiChromaInstance is null!"); reconnect = true; ConnectionStatus = RECONNECT_CHROMA_API_NULL; ThreadWaitForSecond(); } else { //Uri uri = new Uri(_sApiChromaInstance.ApiClient.BasePath); //LogOnMainThread(string.Format("Monitoring Heartbeat {0}...", uri.Port)); while (_sWaitForExit && null != _sApiChromaInstance) { DateTime timeout = DateTime.Now + TimeSpan.FromSeconds(5); try { Thread thread = new Thread(new ThreadStart(() => { try { // The Chroma API uses a heartbeat every 1 second _sApiChromaInstance.Heartbeat(); } catch (Exception /* ex */) { //Debug.LogError(string.Format("Failed to invoke action! {0}", ex)); } })); thread.Start(); while (_sWaitForExit && DateTime.Now < timeout && thread.IsAlive) { Thread.Sleep(0); } if (_sWaitForExit && timeout < DateTime.Now && thread.IsAlive) { //Debug.LogError("Heartbeat: Timeout detected!"); thread.Abort(); reconnect = true; } } catch (Exception) { //LogErrorOnMainThread("Failed to check heartbeat!"); reconnect = true; ConnectionStatus = RECONNECT_CHROMA_API_HEARTBEAT_FAILURE; ThreadWaitForSecond(); } if (timeout < DateTime.Now) { //LogErrorOnMainThread("Timeout detected!"); reconnect = true; ConnectionStatus = RECONNECT_CHROMA_API_HEARTBEAT_TIMEOUT; ThreadWaitForSecond(); } if (reconnect) { break; } //LogOnMainThread(string.Format("Monitoring Heartbeat {0}...", uri.Port)); _sConnected = true; _sConnecting = false; ConnectionStatus = CONNECTED; ThreadWaitForSecond(); } //LogOnMainThread(string.Format("Heartbeat {0} exited", uri.Port)); _sConnected = false; _sConnecting = false; ConnectionStatus = NOT_CONNECTED; ThreadWaitForSecond(); } if (reconnect) { ThreadWaitForSecond(); if (_sWaitForExit) { RunOnMainThread(() => { if (_sWaitForExit) { Connect(); } }); } } }