我正在开发 c# windows 服务,它将监视多个文件、文件夹和数据库表的任何更改。观察者分为三种类型(我称它们为观察者)。
FileWatcher :使用 .Net FileSystemWatcher持续监视文件并引发要发送警报的事件。发送警报后,手表功能恢复。
FolderWatcher:使用 .Net Timer持续监视文件夹并引发在特定条件下发送警报的事件。发送警报后,手表功能恢复。
DBWatcher:每分钟(定时器)执行一次 SQL 查询,如果结果错误则发送警报。
你可以猜到,这些所有的观察者都会一直运行在 windows 服务运行的地方。
它们都实现了一个接口IWatcher并提供了一个BeginWatch方法,该方法执行每个 watcher 所需的操作,例如使用 timer 每分钟查询一次 DB(如果 watcher 是 DBWatcher)。创建这些观察者的输入是一个 XML 文件。它包含如下内容:
<?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>
这个 XML 告诉我们要创建多少个观察者。可以创建数十个观察者。
由于我们面临的一些问题,我们决定每个观察者将在不同的线程上运行。因此,如果出现未处理的异常,只能停止/终止该线程,我们会通过电子邮件警报通知 IT 部门有关情况。我们必须能够在以后恢复它。
现在我很困惑。因为有线程、异步任务、池线程、后台线程等。我应该使用什么???/我是这个线程的新手。
让我告诉您我的要求,然后您可以指导我找到一些适当的解决方案:
- 我希望每个观察者都在单独的线程中运行。
- 线程必须连续运行,并且我的观察者必须能够观察到 Windows 服务本身关闭。
- 线程必须能够与其父线程(创建每个线程的类)通信以更新其状态。
- 线程中任何未处理的异常都必须在线程本身中捕获,然后传递给父类(使用第 3 点)。
我创建了以下类,它将负责创建、通信和管理所有线程:
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?
}
}
}
实现我想要的最好方法是什么?