public void Start(IFthService service) { if (!ServiceThreads.ContainsKey(service)) { var t = Fi.Tech.SafeCreateThread(() => { try { var rt = service.Run(); if (rt != null) { rt?.Wait(); } if (service is IFthCyclicService cServ) { var rt2 = cServ.MainLoopInit(); if (rt2 != null) { rt2?.Wait(); } cServ.BreakMainLoop = false; cServ.InterruptIssued = false; Task[] lt = new Task[1]; int l = 0; while (!cServ.BreakMainLoop && !cServ.InterruptIssued) { lt[l] = cServ.MainLoopIteration(); var prev = (l - 1) >= 0 ? l - 1 : lt.Length - 1; if (lt[prev] != null && !lt[prev].IsCompleted) { lt[prev].Wait(); } l = (l + 1) % lt.Length; try { Task.Delay(cServ.IterationDelay, CyclicServiceIterationResets[cServ].Token).Wait(); } catch (Exception) { // this catch is because .Net throws on cancellation, cancelling is part of the main plan // not the exceptional case for us here. } finally { CyclicServiceIterationResets[cServ] = new CancellationTokenSource(); } } } } catch (Exception x) { Fi.Tech.WriteLine($"Error Executing Service {service.GetType().Name} {x.Message}"); OnServiceError?.Invoke(service, x); } }); t.IsBackground = !service.IsCritical; t.Name = $"fthservice_{idgen++}_{service.GetType().Name}"; t.Start(); Services.Add(service); ServiceThreads[service] = t; ServiceInfos[service] = new FthServiceInfo(service); CyclicServiceIterationResets[service] = new CancellationTokenSource(); } }
public IFthService InitService(Type svcType, params object[] args) { var svc = Services.FirstOrDefault(s => s.GetType() == svcType); if (svc != null) { return(svc); } if (svcType != null) { IFthService instance = (IFthService)Activator.CreateInstance(svcType); instance.Init(args); Services.Add(instance); return(instance); } return(null); }
public void Stop(IFthService service) { if (ServiceThreads.ContainsKey(service)) { service.InterruptIssued = true; ServiceThreads[service].Join(TimeSpan.FromSeconds(12)); if (!service.IsCritical) { if (ServiceThreads[service].IsAlive) { ServiceThreads[service].Interrupt(); } ServiceThreads.Remove(service); ServiceInfos.Remove(service); CyclicServiceIterationResets.Remove(service); } } }
internal FthServiceInfo(IFthService service) { this.Name = service.GetType().Name; }