I want to devleop a custom system for my self.
I want to loading custom services by configuratin with dependency services - for example:
<Services><Service name="ServiceA" args="" type="IServiceA" dependencies=""/><Service name="ServiceB1" args="" type="IServiceB1" dependencies="ServiceA"/><Service name="ServiceB2" args="" type="IServiceB2" dependencies="ServiceA"/><Service name="ServiceC1" args="" type="IServiceC1" dependencies="ServiceA,ServiceB1"/><Service name="ServiceC2" args="" type="IServiceC2" dependencies="ServiceA,ServiceB2"/><Service name="ServiceD" args="" type="IServiceD" dependencies="ServiceA,ServiceB2,ServiceC2"/><Service name="ServiceE" args="" type="IServiceE" dependencies="ServiceA,ServiceB2,ServiceC2,ServiceD"/><Service name="ServiceF" args="" type="IServiceF" dependencies="ServiceA,ServiceB1,ServiceC1,ServiceD,ServiceE"/></Services>
All those services are implement custom interface:
public interface IService
{
bool Start();
bool Stop();
bool IsReady {get;}
event EventHandler Stopped;
}
I perform a topological sort and i getting:
Level 0: ServiceA
Level 1: ServiceB1, ServiceB2
Level 2: ServiceC2, ServiceC2
Level 3: ServiceD
Level 4: ServiceE
Level 5: ServiceF
So i loop every level and start a services...
It's good enough?
var sortedGroups = PerformLogicalSort();
foreach (var group in sortedGroups)
{
List<Task<bool>> tasks = new List<Task<bool>>();
foreach (var module in group.Value)
{
var task = Task.Factory.StartNew<bool>(() =>
{
try
{
Console.WriteLine("TaskUserWorkItem " + module.Id +" is started...");
module.Start();
while (!module.IsReady)
{
Console.WriteLine("TaskUserWorkItem " + module.Id + " still not ready..");
Thread.Sleep(1000);
}
Console.WriteLine("TaskUserWorkItem " + module.Id + " is ready..");
if (module.Dependencies != null && module.Dependencies.Count > 0)
{
foreach (var depend in module.Dependencies)
{
dependModule.Stopped += (a, b) =>
{
if (IsShuttingDown)
return;
if (!module.IsReady)
return; //has been stoped allready
module.Stop();
while (!DependenciesReady(module.Dependencies))
{
Console.WriteLine("Module " + module.Id + " Postponed until all its dependecies will be ready");
Thread.Sleep(1000);
}
Console.WriteLine("all dependecies of Module " + module.Id + " are ready.");
Console.WriteLine("TaskUserWorkItem " + module.Id + " is started...");
module.Start();
};
}
}
return true;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return false;
});
tasks.Add(task);
}
bool connected = true;
Task.Factory.StartNew(()=>
{
while(connected)
Console.WriteLine("Level " + group.Key +" : still not ready");
});
Task.WaitAll(tasks.ToArray());
connected = false;
foreach (var task in tasks)
{
if (!task.Result) return;
}
}