4

I am developing c# windows service that will be watching several files, folders and DB tables for any changes. There are three types of watchers (I call them watchers).

  1. FileWatcher : Constantly watcher for a file using .Net FileSystemWatcher and raises an event where alert is to be sent. After alert is sent, watch functionality resumes.

  2. FolderWatcher : Constantly watcher for a folder using .Net Timer and raises an event where alert is to be sent upon certain conditions. After alert is sent, watch functionality resumes.

  3. DBWatcher: Executes an SQL query after each minute (Timer) and sends an alert if the result is wrong.

You can guess that these all watchers will run all the time where windows service is running.

They all implement an interface IWatcher and provide a method BeginWatch that performs the operations needed for each watcher, such as querying the DB every minute using timer (if watcher is DBWatcher). The input for creating these watchers is an XML file. It contains something like following:

<?xml version="1.0" encoding="utf-8"?>
<watchlist>

    <watcher type="FolderWatcher">
        <path>D:\Projects\.Net\V1\</path>
        <PauseInMinBtwAlerts>1</PauseInMinBtwAlerts>
        <alert>xxx@xxx.com</alert>
    </watcher>

    <watcher type="FileWatcher">
        <path>D:\Projects\.Net\</path>
        <fileName>e.txt</fileName>
        <alert>yyy@yyy.com</alert>
    </watcher>

    <watcher type="DBWatcher">
        <sqlquery>select blah blah blah ... </sqlquery>
        <connectionstring>connection string for the DB</connectionstring>
        <alert>yyy@yyy.com</alert>
    </watcher>

</watchlist>

This XML tells us how many watchers are to be created. There can be a dozens of watchers created.

Due to some issues we faced, we have decided that each watcher will be run on a different Thread. So in case of an unhandled exeption, only that thread can be stopped/killed and we inform the IT department through an email alert about the situation. We must be able to resume it later.

Now i m confused. as there are Threads, Async tasks, pooled threads, background threads etc etc. what should I use???/ I m new to this threading.

Let me tell you my requirement and then you may guide me to some proper solutions:

  1. I want each watcher to run in a separate thread.
  2. Thread MUST run continuously and my watcher must be able to watch until the windows service itself shuts down.
  3. Thread must be able to communicate with its parent thread (the class where each thread is created) to update it about its status.
  4. Any unhandled exception in a thread must be caught in the thread itself and then communicated to the parent class (using 3rd point).

I have created the following class that will be responsible for creating, communicating with, and managing all threads:

public class WatcherThreadsManager
{
    //This will keep list of all active threads ... as I will be communicating with them later
    private List<Thread> _watcherThreads;

    public WatcherThreadsManager()
    {
        this._watcherThreads = new List<Thread>();
    }

    //I will call this method and pass in any watcher which i want to run in a new thread
    public void CreateWatcherThread(IWatcher watcher)
    {
        Thread _watcher = new Thread(_createWatcherThread);

        //the Copy() will produce its deeply copied copy ... i wanted to make sure thread works on a free object .. not sure
        _watcher.Start(watcher.Copy());

        //Add Thread to threads' list
        this._watcherThreads.Add(_watcher);
    }

    private void _createWatcherThread(object wat)
    {
        IWatcher watcher = wat as IWatcher;
        try
        {
            //the following function will begin the watch.
            //I dont want any loop either .. as i want to call the BeginWatch() method only once.
            watcher.BeginWatch();
        }
        catch (Exception ex)
        {
            // i should be able to inform the parent thread about the exception so this thread is set to sleep. as we can reactivate it later when the issue fixes.
            // how to do that?
        }
    }
} 

What would be the best way to achieve what I want?

svick
  • 236,525
  • 50
  • 385
  • 514
Aamir
  • 1,747
  • 5
  • 26
  • 50
  • why would `watcher.BeginWatch();` throw an exception?? Can you give us some context? – Ahmed KRAIEM May 03 '13 at 14:34
  • I don't think you need FileSystemWatchers to run in separate threads. If the processing of events takes a long time, you may want the Event Handlers to be in separate threads. – Steve Wellens May 03 '13 at 14:36
  • the BeginWatch() method in each watcher (DB, File and Folder) does alot of functions such as staring timers.. calling db.. checking file/folder constantly etc ... so it may through some unhandled exception... e.g if the sql stament for DB writer has errors, then executing that query will generate an exception.. and i want that to be caught in this catch phrase ... it can be any unhandled exception – Aamir May 03 '13 at 14:39
  • And if `watcher.BeginWatch();` throws an exception when would the watcher be reactivated? – Ahmed KRAIEM May 03 '13 at 14:42
  • There are several open-source solutions you could potentially use/ pull inspiration from. WolfPack is a pretty well put together example: http://wolfpack.codeplex.com/ – Chris May 03 '13 at 15:07
  • @Ahmed Kraiem: on exception, an alert/email would be sent to admin and this watcher will be disabled. Admin can reactivate the watcher/thread. Default time would be 6 hours. So if nobody reactivates the watcher earlier, then it will be automatically reactivated after 6 hours. – Aamir May 03 '13 at 16:14
  • @Chris, thanx.. indeed it looks good. I read its introduction. It said its build in .net 4.0. i downloaded it but they are all compiled dlls. no code to take inspiration from. :( – Aamir May 03 '13 at 20:00
  • On the codeplex page, you'll notice three tabs in this order: Home| Source Code | Downloads Clicking on Source Code will allow you to browse through the WolfPack code. It's not quite the same as pulling it down locally, but certainly worth taking a look through. – Chris May 03 '13 at 20:25

2 Answers2

4

You can achieve all of your requirements by using Tasks, here are few links for further reading:

  1. Creating threads - Task.Factory.StartNew vs new Thread()

  2. Best Practice LongRunning Task creation

  3. Task Report Progress

  4. Handling Task exceptions

Good luck!

Community
  • 1
  • 1
Alex S
  • 1,171
  • 1
  • 9
  • 25
  • [Answer containing just a list of links is not very useful.](http://meta.stackexchange.com/q/8231/130186) – svick May 03 '13 at 15:19
  • @svick You are just mad that I replied first ;) I provided answer to original question "What would be the best way to achieve what I want?" - "You can achieve all of your requirements by using Tasks" – Alex S May 03 '13 at 15:26
  • That statement is so general that it's not useful. *How* exactly would you use `Task`s for this? – svick May 03 '13 at 15:55
  • 1
    @svick Have you read the entire post by op? One of his questions was "Now i m confused. as there are Threads, Async tasks, pooled threads, background threads etc etc. what should I use???/ I m new to this threading." following with the list of application requirements. To prevent duplicated asnwers, I provided my support for use of tasks and links to existing answers on this site. Hope you are having a great day! – Alex S May 03 '13 at 16:24
  • @AlexS: Thanks for guiding me toward TPL. I have used that library and learnt as well. – Aamir May 09 '13 at 07:02
1

Due to some issues we faced, we have decided that each watcher will be run on a different Thread. So in case of an unhandled exeption, only that thread can be stopped/killed

This sounds like you don't need threads, you need to catch your exceptions. Why don't you do that?

svick
  • 236,525
  • 50
  • 385
  • 514
  • there can be dozens of watchers created, each with its own duty to constantly watch over something. so will it not be a good idea that each of them executes in a separate thread? – Aamir May 03 '13 at 16:55
  • @Aamir I don't see why would they need that. – svick May 03 '13 at 17:34