sharp-trading/services/ServiceManager.cs

183 lines
4.0 KiB
C#

using System;
using System.Threading;
using System.Collections.Generic;
using System.Diagnostics;
using System.Security.Permissions;
using sharp.extensions;
using sharp.json;
using System.IO;
namespace sharp.trading.services
{
public class ServiceManager
{
public static ServiceManager Default { get; private set; } = new ServiceManager();
public static void ReplaceDefault(ServiceManager newDefault){
if (Default != null){
Default.Shutdown();
}
Default = newDefault;
}
Thread serviceThread;
bool shutdown = false;
List<ScheduledService> scheduledServices = new List<ScheduledService>();
public ServiceManager()
{
serviceThread = new Thread(_scheduler);
serviceThread.Start();
Load();
}
public void Shutdown(){
lock (this){
shutdown = true;
}
while (serviceThread.IsAlive){
Thread.Sleep(250);
}
foreach (ScheduledService service in scheduledServices){
while (service.IsRunning){
Thread.Sleep(250);
}
service.TradingService.Shutdown();
}
Save();
}
private void Load(){
if (File.Exists(Path.Combine(TradingEnvironment.DataDirectory, "services.json"))){
JSON json = JSON.ReadFrom(Path.Combine(TradingEnvironment.DataDirectory, "services.json"));
ConstructableObject[] cos = json.To<ConstructableObject[]>();
foreach (ConstructableObject co in cos){
ITradingService its = (ITradingService)co.Construct();
Schedule(its,true);
}
}
}
public void Save(){
List<ConstructableObject> col = new List<ConstructableObject>();
lock (this){
foreach (ScheduledService sservice in scheduledServices){
ConstructableObject co = new ConstructableObject(sservice.TradingService);
col.Add(co);
}
}
JSON json = JSONConverter.From(col.ToArray());
json.WriteTo(Path.Combine(TradingEnvironment.DataDirectory,"services.json"),true);
}
public void Schedule(ITradingService service, bool RunImmediate = false){
lock (this){
ScheduledService sservice = new ScheduledService(service);
if (RunImmediate){
sservice.ScheduledRun = DateTime.UtcNow.Ticks;
}
scheduledServices.Add(sservice);
}
}
public void Unschedule(ITradingService service){
lock (this){
foreach (ScheduledService sserv in scheduledServices.ToArray()){
if (sserv.TradingService == service){
scheduledServices.Remove(sserv);
break;
}
}
}
}
void _scheduler(){
while (true){
try {
Thread.Sleep(1000);
} catch (Exception e){
}
if (shutdown){
break;
}
lock(this){
foreach (ScheduledService sservice in scheduledServices){
if (sservice.HasElapsed){
//ThreadPool.QueueUserWorkItem((state) => sservice.Run());
sservice.Run();
}
}
}
}
}
class ScheduledService {
public Int64 ScheduledRun { get; set; }
public Int64 ScheduledIntervall { get; private set; }
public ITradingService TradingService { get; private set; }
bool isRunning;
public bool IsRunning {
get { lock (this) { return isRunning; } }
private set { lock(this) { this.isRunning = value; } }
}
public ScheduledService(ITradingService tradingService){
this.TradingService = tradingService;
this.ScheduledRun = DateTime.UtcNow.Ticks + (tradingService.SchedulingIntervall() * 10000000);
}
public bool HasElapsed {
get
{
return ScheduledRun <= DateTime.UtcNow.Ticks;
}
}
public void Run(){
lock(this){
if (!IsRunning){
IsRunning = true;
} else {
Console.WriteLine("Service already running, re-scheduling...");
ScheduledRun += ScheduledIntervall;
return;
//throw new Exception("Tried to run ScheduledService while already running");
}
ScheduledIntervall = TradingService.SchedulingIntervall() * 10000000;
ScheduledRun += ScheduledIntervall;
}
try {
TradingService.RunService();
} catch (Exception e){
Console.WriteLine("ScheduledService threw exception: {0}",e.ToString());
}
IsRunning = false;
}
}
}
}