0

I've search over the web but I think I have more a comprehension problem then a technical one.. And by beeing an intensive S.O. reader, I know that I must expose my total requirment rather then ask my question simply...so...

Dev stuff : Visual studio 2010 (..), C#, target framework 3.5 client profile..

My basic requirement:

Here is my requirment : I want to have a downloadable software that will install on client computers. This tools will periodically do some tasks [download some sales data (invoices, orders] from a precise ERP System that we work with.
I dont want the user to necessary be logged-in to let my tool work (if the computer reboot, I want my tool to start anyway). So here, a standard Windows Service seems the best choice, with a front-end application to allows setting some options, and seeing the status of the worker. At this point, I have a Windows Service (c# 3.5) and a front-end tool. Note that it worked fine for me at this point. In the OnStart method of my service, I "initiate" all my stuff (prepare folders, get options, connect to my remote SQL Server on the cloud, validate that the system is good, and then wait for the tasks, with a timer checking for tasks to run). Until here, everything work as expected.

Advanced communication between front-end tool and my Windows Service

Now, I want to talk/ask things to my service from my Front-end tool. I want to ask ("How many process are you runing right now", "what is your actual timer state", "which tables are you currently running", "Abort all your tasks" , etc...). I've tried a little bit "Custom Command" by sending custom command to my Windows Service, but it is really restricted : In order to know the Answers of a question "Which tables are you currently loading", I tried to write in a custom event Log, and retrieving that from my Front-end application, but I dont find that clean as I may want to have a rapid and reapeted feedback from my tool (for instance, seeing the progess of ONE table beeing loaded, refreshed each 5 secondes). There is also the writing to a file on the hard-drive, but I may want to have my service hosted on another computer then the front-end tool.

The WCF Path

Option 1 - The WCF Service is only a communicator, nothing more.

So, as found on internet, I've started to look at the hosted WCF Service option. So first, I only added a simple and gentle WCF Service library inside my Main Windows Service. That sub-WCF-service would only respond to complex questions from the front-end tool, and then ask his creator (the main Windows Service) for the responses. My basic setup worked -> in the OnStart of my Windows Servbice, I initiate all my business stuff, AND started (HostService) my WCF Service to listen. But I dont see any way to have a full linked between my Windows Service and my WCF Service (to be able to access the main Service complex informations). Static method? passing the main "statuses" classes to the WCF service, but how? ..

Option 2 - The Wcf Service is Everything.

Then, I tried to move ALL my code inside my WCF Service, saying "ok, why to have 2 assemblies if only ONE can do the trick". So in the OnStart of my basic Windows Service, no more initiating of my busines stuff. Only Starting the sub-WCFServices. Everything seems fine at the conceptual level. But how can I say "ok, WCF Service, Start to listen, and initiate the business stuffs"? I dont find nothing about "launching code on startup" of a WCF Service. On the web, i see a lot of "WCF Service are mainly for 'on call' basis. But I want the WCF service to do all my stuff (load table, upload them to the cload, etc...) via the timer AND be able to have a talk with the front-end tool. Must I, in the main Windows Service, create the WCF Service, And immediallety connect to it to ask for a particular exposed method (via the service contract)?

So, my question : 1 - does my architecture make sense? 2 - Does the WindowsService->WCFService hosting makes sense for my requirement? 3 - Should I move all my code the the WCF Service library? or not

thanks a lot!

Simon


Edit:

Thanks FerretallicA!

Honestly, I prefer having everything well separated. So I like your idea of passing a reference of my class to my WCF Service.

Just for more complete stuff, here is my OnStart method of my main Windows Services :

Note : (lot of the code come from : How to: Host a WCF Service in a Managed Windows Service

   protected override void OnStart(string[] args)
    {
        //The MyMainClass is global to my service.  
        MyMainClass = new DailyExtraction_MainClass();

        //initiating the worker (setting the timer ticks,  basic connexion,etc....)
        MyMainClass.Initialiser_Robot_Extracteur(); 


        //Write some log through my Worker 
        MyMainClass.MyLogExecution.WriteLog(" - End of OnStart()");

        **//Here is the WCF Sub-service creation**
        try
        {
            if (myWCFServiceHost != null)
            {
                myWCFServiceHost.Close();
            }

            // Create a ServiceHost for my class type and .
            myWCFServiceHost = new ServiceHost(typeof(DailyExtractionUtils.CloudBI_Communicator));

            // Open the ServiceHostBase to create listeners and start 
            // listening for messages.
            myWCFServiceHost.Open();


        }
        catch (Exception ex)
        {
            MyMainClass.MyLogExecution.WriteLog(" - Error while trying to create the WCF Service");
        }
    }

So, I try to figure out where must I pass the reference to my "MyMainClass" class.

NOTE: I've just re-searched on your idea "how to pass reference to the sub wcf-service" and I found that : S.O. question - WCF call that references Windows Service. I'll read that in depth later on.

Community
  • 1
  • 1
Simon
  • 2,266
  • 1
  • 22
  • 24

2 Answers2

0
  1. Whether this is viable in your circumstance or not will depend on your service design but the two general approaches I would consider for exposing service A to B with the overall design you've presented:

    • pass a reference to the main service instance to the WCF / monitoring service in the constructor
    • if using something like Castle Windsor, register your main service as a singleton so the monitoring service can access the main service instance from various points
  2. It's fine

  3. It's not necessary at all, but depending on the nature of the main service it might make sense to expose the monitoring functionality in a consistent manner with the primary functionality.

nathanchere
  • 8,008
  • 15
  • 65
  • 86
0

[I realize that this thread is older but I myself read over these types of Q&A sessions for guidance; others might be following along because they have similar concerns.]

Usually in the initial platform design I would suggest the following rule of thumb: begin with the end. In other words, imagine yourself implementing this and ask where you're going to host it. If you are hosting it in the cloud in many cases the part that talks to the end-user can be increased or decreased in number of instances to scale up to the demand. In this scenario you might have one or two instances of the backend analytics part that actually has the data. If I thought it might be later hosted somewhere in the cloud I would favor the separation approach in Option 1 above.

Also, I think I would consider things such as the task point where you're connecting to the ERP system itself. Does this part require a simple, native-Microsoft ODBC connection or does it require some third-party connectivity like QODBC or similar? Is there a per-workstation charge for this? Secondly, year after year if the ERP system is upgraded will this require an upgrade to the communication piece? (Imagine having to then upgrade all the client softwares to keep up.) For these reasons I prefer moving this piece to a server somewhere either locally or cloud-hosted. You'd connect with one centralized server to the ERP system and it exposes the analyzed data to the other software you've made.

So the implementation I think I would go with would be a WCF service that runs on a local server as combined with the client-side piece that runs on command by the end-user. The end-user piece isn't a service because it wouldn't need to be.