Click here to Skip to main content
15,917,568 members
Home / Discussions / C#
   

C#

 
GeneralRe: Scheduled Services Architecture - Prototype Pin
Kevin Marois30-Mar-17 4:30
professionalKevin Marois30-Mar-17 4:30 
AnswerRe: Scheduled Services Architecture - Prototype Pin
Nathan Minier30-Mar-17 1:30
professionalNathan Minier30-Mar-17 1:30 
AnswerRe: Scheduled Services Architecture - Prototype Pin
Pete O'Hanlon3-Apr-17 2:26
mvePete O'Hanlon3-Apr-17 2:26 
GeneralRe: Scheduled Services Architecture - Prototype Pin
Kevin Marois3-Apr-17 5:38
professionalKevin Marois3-Apr-17 5:38 
QuestionVisual C# Frameworks Pin
zequion28-Mar-17 20:43
professionalzequion28-Mar-17 20:43 
AnswerRe: Visual Studio 2017 Defective Editor in Design Mode Pin
Eddy Vluggen28-Mar-17 22:54
professionalEddy Vluggen28-Mar-17 22:54 
AnswerRe: Visual C# Frameworks Pin
Kevin Marois29-Mar-17 4:18
professionalKevin Marois29-Mar-17 4:18 
QuestionScheduled Services Architecture Pin
Kevin Marois28-Mar-17 7:53
professionalKevin Marois28-Mar-17 7:53 
This is a bit long but I really need some validation on my project. I would appreciate your thoughts on the overall design and also my questions at the end

Overview
I'm creating an app that will run individual assemblies (called "Services") in a Windows Service. The Windows Service will really just be a host for the service classes that can be run according to a schedule. A "Service" is just an an assembly that implements an interface. Its run duration is determined by a schedule. It can run one time, or repeatedly according to scheduling options.

The Windows Service will be running on remote instruments around the world. The Windows Service will listen to a SignalR service running on our server that will all us to install, start, stop, disable, remove, or change the schedule for any or all of the "Services" on a particular instrument.

An example of a use case is diagnostics. A service will execute every 5 minutes to query a local DB for error records, then report its findings back to our server. The will be other use cases as well.

Details
On startup of the Windows Service the app will load services from a 'manifest'. This file is just a serialized list of services to load and when to run them. If an assembly is not runable (because the schedule says not to run, or it's been disabled), the it's not loaded.

Here's the manifest, not including the scheduling details.
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfService xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Service>
    <ServiceName>TestClass1</ServiceName>
    <ServiceId>59182d7e-8874-4d40-bdba-44936bcce815</ServiceId>
    <AssemblyName>Services.Test.dll</AssemblyName>
    <State>Ready</State>
  </Service>
</ArrayOfService>
Assemblies that can be run will implement this interface
public interface IService
{
    event EventHandler<ServiceMessageModel> StatusChanged;

    string ServiceName { get; set; }

    Guid ServiceId { get; set; }

    ServiceState State { get; set; }

    void Start();

    void Stop();
}
For each item in the manifest the app will create an instance of each class and store that reference in a list:
private void LoadServices()
{
    _services = new List<IService>();

    string[] files = Directory.GetFiles(_servicesLocation, "*.dll");

    foreach (string file in files)
    {
        var assemblyExistsInManifest = _manifest.Where(x => file.Contains(x.AssemblyName)).Any();
        if (assemblyExistsInManifest)
        {
            Assembly assembly = Assembly.LoadFrom(file);
            var types = assembly.GetTypes();

            foreach (Type type in types)
            {
                var typeExistsInManifest = _manifest.Where(x => type.ToString().Contains(x.ServiceName)).Any();

                var implementsInterface = typeof(IService).IsAssignableFrom(type);

                if (typeExistsInManifest && implementsInterface)

                    var serviceClass = Activator.CreateInstance(type) as IService;
                    serviceClass.StatusChanged += ServiceClass_StatusChanged;

                    _services.Add(serviceClass);
                }
            }
        }
    }
}
Next, the list is iterated and each service in it is started in its own thread
private void StartAllServices()
{
    foreach (var service in _services)
    {
        Task.Factory.StartNew(() =>
        {
            service.Start();

        });
    }
}

This is the basic idea and some code that I already have in place.

Questions
1) Cancelling / Pausing. I need to be able to stop a service from further processing. This could mean the service remains loaded but does not continue processing, or it could mean actually cancelling the task the service is running is so it can be unloaded.

This means that I would need to store separate CancellationTokenSource instances for each service as they're loaded in the StartService method above so that I can call Cancel() on a task for a specific service. If I defined the CancellationTokenSource as a property on the IService interface, then the StartServices method could create the CancellationTokenSource and assign it to the service at the time it is started.

This would allow my CancelService method to look like this
C#
private void CancelService(Guid serviceId)
{
    // Find the service class for the speified Id
    var service = _services.FirstOrDefault(x => x.ServiceId == serviceId);

    // If it was found...
    if (service != null)
    {
        // Cancel the task
        var ct = service.CancellationToken; // Get the token off the service.
        ct.Cancel();
    }
}
Any thoughts on this?

2) Error Handling. Assuming an exception happens inside a service, this should not "crash" the service but instead set its State to Error and report that to the Host running on our server. The Windows Service portion should catch exceptions thrown by the services and report that back to the server. At no point should an exception cause either the Windows Service or any service to stop running. Any thoughts on this?

Summary
I'm VERY new to TPL and have little to no experience with it, so this design may be totally wrong. If so, please share your thoughts on a more stable approach. I would also appreciate any example code you may have.

Thank you
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.


modified 28-Mar-17 14:42pm.

AnswerRe: Scheduled Services Architecture Pin
Bernhard Hiller28-Mar-17 21:13
Bernhard Hiller28-Mar-17 21:13 
GeneralRe: Scheduled Services Architecture Pin
Kevin Marois29-Mar-17 4:15
professionalKevin Marois29-Mar-17 4:15 
GeneralRe: Scheduled Services Architecture Pin
Kevin Marois29-Mar-17 4:19
professionalKevin Marois29-Mar-17 4:19 
QuestionHandle Exception In Thread Pin
Kevin Marois27-Mar-17 9:35
professionalKevin Marois27-Mar-17 9:35 
AnswerRe: Handle Exception In Thread Pin
Rob Philpott28-Mar-17 0:01
Rob Philpott28-Mar-17 0:01 
GeneralRe: Handle Exception In Thread Pin
Kevin Marois28-Mar-17 5:55
professionalKevin Marois28-Mar-17 5:55 
AnswerRe: Handle Exception In Thread Pin
Nathan Minier28-Mar-17 1:35
professionalNathan Minier28-Mar-17 1:35 
AnswerRe: Handle Exception In Thread Pin
Richard Deeming28-Mar-17 1:43
mveRichard Deeming28-Mar-17 1:43 
QuestionC# Read random line Pin
Pavlex426-Mar-17 10:00
Pavlex426-Mar-17 10:00 
AnswerRe: C# Read random line Pin
Dave Kreskowiak26-Mar-17 12:52
mveDave Kreskowiak26-Mar-17 12:52 
AnswerRe: C# Read random line Pin
Garth J Lancaster26-Mar-17 13:50
professionalGarth J Lancaster26-Mar-17 13:50 
AnswerRe: C# Read random line Pin
OriginalGriff26-Mar-17 21:37
mveOriginalGriff26-Mar-17 21:37 
GeneralRe: C# Read random line Pin
Pavlex426-Mar-17 21:52
Pavlex426-Mar-17 21:52 
GeneralRe: C# Read random line Pin
OriginalGriff26-Mar-17 22:12
mveOriginalGriff26-Mar-17 22:12 
GeneralRe: C# Read random line Pin
Pavlex426-Mar-17 23:41
Pavlex426-Mar-17 23:41 
GeneralRe: C# Read random line Pin
Pete O'Hanlon26-Mar-17 23:45
mvePete O'Hanlon26-Mar-17 23:45 
GeneralRe: C# Read random line Pin
Pavlex427-Mar-17 0:03
Pavlex427-Mar-17 0:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.