/// <summary> Creates a thread that loops a specific body, at a specific rate.</summary> /// <param name="body"> code to execute, returns true each cycle to continue, and false if it wants to stop itself. </param> /// <param name="rate"> Milliseconds to wait between loops </param> /// <param name="stopOnError"> If an error occurs internal to the function, should it terminate the thread? </param> /// <returns> ThreadStart delegate wrapping body/rate parameters. </returns> public ThreadStart Loop(Func <bool> body, int?rate = null, bool stopOnError = false) { // We are implicitly capturing function params, but, // since this should not be used very often, should not cause memory leak. return(() => { DateTime last = DateTime.UtcNow; while (Running) { DateTime now = DateTime.UtcNow; try { bool keepGoing = body(); if (!keepGoing) { break; } } catch (Exception e) { Log.Error("Failure in Server.Loop", e); if (stopOnError) { break; } } ThreadUtil.Hold(rate ?? 1); } }); }
/// <summary> Loop for sending data to connected clients. @Todo: Pool this. </summary> private void SendLoop() { while (Running) { SendPass(); ThreadUtil.Hold(1); } string id = isSlave ? "Slave" : "Master"; Log.Info($"SendLoop Ending for {id}"); }
/// <summary> Loop for recieving data from connected clients. @Todo: Pool this. </summary> private void RecrLoop() { while (Running) { try { RecrPass(); } catch (Exception e) { Log.Error("Failure in Server.RecrLoop", e); } ThreadUtil.Hold(1); } string id = isSlave ? "Slave" : "Master"; Log.Info($"RecrLoop Ending for {id}"); }
private void GlobalUpdateLoop() { long i = 0; while (Running) { GlobalUpdatePass(); // Log.Info($"On update tick {i}"); i++; ThreadUtil.Hold(1); } string id = isSlave ? "Slave" : "Master"; Log.Info($"Updates stopping for {id} and cleaning up."); //Todo: Cleanup work }
private void GlobalUpdate() { while (Running) { try { RPCMessage msg; while (incoming.TryDequeue(out msg)) { if (msg.sender.closed) { // early break??? // maybe we still want to handle messages when closed // eg, ServerShuttingDown } HandleMessage(msg); } HandleInternalEvents(); } catch (Exception e) { Log.Error("Failure in Server.GlobalUpdate during Handlers: ", e); } DateTime now = DateTime.UtcNow; TimeSpan diff = now - lastTick; try { if (diff.TotalMilliseconds > tickRate) { lastTick = now; float d = (float)diff.TotalSeconds; foreach (var pair in services) { pair.Value.OnTick(d); } } } catch (Exception e) { Log.Error("Failure in Server.GlobalUpdate during Ticks: ", e); } ThreadUtil.Hold(1); } string id = isSlave ? "Slave" : "Master"; Log.Info($"Updates stopping for {id} and cleaning up."); //Todo: Cleanup work }
/// <summary> Loop for recieving data from connected clients. @Todo: Pool this. </summary> private void RecrLoop() { while (Running) { try { Client c; if (recrCheckQueue.TryDequeue(out c)) { RecieveData(c); if (!c.closed) { recrCheckQueue.Enqueue(c); } } } catch (Exception e) { Log.Error("Failure in Server.RecrLoop", e); } ThreadUtil.Hold(1); } string id = isSlave ? "Slave" : "Master"; Log.Info($"RecrLoop Ending for {id}"); }