Windows Service application architecture doubts

2019-09-12 17:51发布

问题:

I need to create some Windows Service App (C#) that should perform several periodically executed and binded to each other tasks like:

  1. Watch for folder changes.
  2. Send files to Web Services (Web API).
  3. Write Log and keep it in local DB.

So I am wandering if I can just use "quickly and dirty" approach and implement all this using BackgroundWorker class or I have use more sophisticated stuff like Tasks y etc (.NET Windows Service - Architectural Decisions). Or event there are some frameworks to do it.

Any advice about possible modern and clean structure of that application would be nice to hear. Thank you very much!

回答1:

Sounds like you'll be needing this on a dedicated server. So my first suggestion is to use TopShelf. It makes putting together modern Windows services so easy its laughable.

Then to perform the steps in your question I'd use some sort of workflow pattern. Windows Workflow Foundation seems to be modern enough to cater for this. (Personally, I just use the chain-of-responsibility pattern with a DI container as my quick and "dirty").

Lastly combining that with an event-driven approach that kicks off the workflow, like FileSystemWatcher, you won't even need to worry about backgroundworkers etc.

So with those architecture decisions made, your service will be easy to setup, run, test and install (TopShelf), and you can build and unit test your service modularly (workflow pattern).



回答2:

I will use worker for the implementation, if you are looking to scale or modern architecture then use cloud like Azure. By using Azure you can implement the it by using Azure Queues. One worker will watch the changes, then enqueue the changes. Another worker for sending the files to web Api by using the queue. Logging you can done as another worker or can done with the same worker.



回答3:

The typical approach is to create a thread to process the information.

public partial class Service1 : ServiceBase
{
    private Timer _timer;
    public Service1()
    {
        InitializeComponent();
        _timer = new Timer(OnDoStuff);
    }

    protected override void OnStart(string[] args)
    {
        _timer.Change(5000, Timeout.Infinite);
    }

    protected override void OnStop()
    {
        _timer.Change(Timeout.Infinite, Timeout.Infinite);
    }

    protected void OnDoStuff(object state)
    {
        //do your things here.



        //activate the timer again.
        _timer.Change(5000, Timeout.Infinite);
    }
}

Using only the first parameter in the Change method for the timer means that it should only run once in 5 seconds. By using that method we are making sure that the timer doesn't start again in parallel if the first invocation doesn't complete within 5 seconds.

Also note that the application will crash if there are an unhandled exception in OnDoStuff, so make sure that you are using a try/catch.

Other than that, using a windows service seems fine for this task.