我的情况是,我创建一个长时间运行的任务列表,用于监控某些系统/网络资源,然后发送电子邮件,日志到txt文件,并且<当满足某些条件时,strong>调用Web服务。然后再次开始监控。这些任务是在Windows服务中创建的,因此将一直运行。
我希望他们引发事件或某事来通知父类(创建它们),它将执行我上面提到的3个操作,而不是执行它的任务中的每个对象。
如何控制只有一个任务一次使用该父类的方法。由于涉及电子邮件和Web服务调用,因此两个并发请求可能会丢失代码。
更新
这些观察者有三种类型,每种都实现以下界面。
public interface IWatcher
{
void BeginWatch();
}
实施的类是
//this watcher is responsible for watching over a sql query result
public class DBWatcher : IWatcher
{
....
void BeginWatch()
{
//Here a timer is created which contiously checks the SQL query result.
//And would Call SERVICE, send an EMAIL and LOG into a file
Timer watchIterator = new Timer(this._intervalMinutes * 60000);
watchIterator.Elapsed += new ElapsedEventHandler(_watchIterator_Elapsed);
watchIterator.Start();
}
void _watchIterator_Elapsed(object sender, ElapsedEventArgs e)
{
//1. Check Query result
//3. Call SERVICE, send an EMAIL and LOG into a file if result is not as was expected
//I have done the work to this part!
//And I can do the functions as follows .. it should be simple.
//*********************
//SendEmail();
//LogIntoFile();
//CallService();
//But I want the above three methods to be present in one place so i dont have to replicate same functionality in different watcher.
//One approach could be to create a seperate class and wrape the above mentioned functions in it, create an instance of that class here and call them.
//Second option, which I am interested in but dont know how to do, is to have this functionality in the parent class which actually creates the tasks and have each watcher use it from HERE ...
}
....
}
//this watcher is responsible for watching over Folder
public class FolderWatcher : IWatcher
{
....
void BeginWatch()
{
///Same as above
}
....
}
首先,我从XML文件创建一个List。这可以包含DBWatcher的多个实例,它将持续观察不同的查询结果和FolderWatcher,它将不断地连续观看不同的文件夹。
创建List之后,我调用我调用的以下函数来创建一个单独的Task。我多次调用此函数来创建一组不同的观察者。
private void _createWatcherThread(IWatcher wat, CancellationTokenSource cancellationToken)
{
//This represents a watcher that will watch some specific area for any activities
IWatcher watcher = wat.Copy();
bool hasWatchBegin = false;
try
{
//run forever
for (;;)
{
//dispose the watcher and stop this thread if CANCEL token has been issued
if (cancellationToken.IsCancellationRequested)
{
((IDisposable)watcher).Dispose();
break;
}
else if (!hasWatchBegin)
{
//This method of a watcher class creates a timer. which will
//continously check the status after a few minutes... So its the
//timer's elapsed method in Watcher object which will send the mail
//& call service etc to update the admin of current status of the watcher.
//this will be called only once in a watcher!
watcher.BeginWatch();
hasWatchBegin = true;
}
}
}
catch (Exception ex)
{
//Watcher has thrown an exception.
//Again, do the following operations
//*********************
//SendEmail();
//LogIntoFile();
//CallService();
}
}
答案 0 :(得分:2)
如果您发送电子邮件,记录和webservice调用threadsafe你可以将对代码的引用传递给监视任务,这些代码作为闭包(这里是Jon Skeet的excellent explanation c#闭包)发送到每个接收器。以下是您需要启动多个任务的示例:
...
void Email(string message){}
void Log(string message){}
void CallWebService(string message){}
void RunMonitoringTask()
{
var task = Task.TaskFactory.StartNew(() =>
{
string message = Monitor();
if( ShouldNotify(message))
{
Email(mesasge);
Log(message);
CallWebService(message);
}
}
)
}
...
修改强>
VS。无限的监视器循环在必要时触发任务:
...
void Email(string message){}
void Log(string message){}
void CallWebService(string message){}
void Monitor()
{
while(true)
{
string message = Monitor();
if(ShouldNotify(message))
{
var task = Task.TaskFactory.StartNew(() =>
{
Email(mesasge);
Log(message);
CallWebService(message);
}
}
}
)
}
...
至于如何实现这些类,我建议采用一种方法,其中每个接收器都接受消息&amp;然后将其卸载到它自己的处理线程/任务,以避免阻止您的监控任务和举起其他通知。
答案 1 :(得分:0)
Progress
课程非常适合这项任务。它允许长时间运行的进程通知某人(通常是调用者)该操作的当前进度。
Progress<string> progress = new Progress<string>();
progress.ProgressChanged += (s, data) => Console.WriteLine(data);
for (int i = 0; i < 2; i++)
Task.Run(() => DoWork(progress));
public static void DoWork(IProgress<string> progress)
{
int i = 0;
while (true)
{
Thread.Sleep(500);//placeholder for real work
progress.Report(i++.ToString());
}
}
如果要在不同时间报告不同类型的信息,则只需将多个IProgress
实例传递给worker方法。 (或者,如果要同时报告几种类型数据的进度,请将所有数据包装在复合对象中。)
另请注意,这可以处理您所说的所需的同步。 Progress
个实例在创建时会在创建时捕获SynchronizationContext.Current
的值,并将进度更改事件的所有事件处理程序编组到该同步上下文中。因此,如果您的应用程序已经具有上下文(即来自桌面应用程序的UI上下文),那么您可以免费获得该上下文。如果您没有(即它是一个控制台应用程序),那么您需要手动将事件处理程序与lock
同步,或者创建自己的SynchrnonizationContext
以设置为当前上下文