c#可靠的延迟/预定执行最佳实践

我正在进行的项目要求在某个时间执行一些处决。 我不确定处理这种情况的最佳方法是什么。 该方法必须能够在服务器重启/维护后继续存在。 方法调用必须以编程方式进行。

我正在考虑走这条道路:

我可以在数据库(甚至是消息队列)中有一个名为TaskTable的表,它可以具有TaskID(PK),TaskName(varchar),TaskStatus(枚举成功,失败,已调度)和TimeOfExecution。 但我需要一个Windows服务,定期轮询数据库以查找任何未执行的任务。 我面临的问题是:我将什么用作保存到数据库中的TaskName? class级名称? 类和方法名称ToString? 我怎样才能将字符串转换回来并以编程方式调用方法调用(我不希望有一个巨大的switch语句)? 一项持久性的任务如下所示。 所以我需要能够获得任务“SendIncompleteNotification”的名称,并将类名保存到数据库中并以回溯方式调用

public static Task SendIncompleteNotification { get { return new Task ( a => Console.WriteLine("Sample Task") , "This is a sample task which does nothing." ); } } 

现在的问题是我在编译方法/属性名称时遇到问题。

 var type = ApplicationTask.SendIncompleteNotification.GetType(); //type.Name shows "Task`1" rather than SendIncompleteNotification 

有没有更好的方法来处理这种情况? 谢谢!

更新:对不起,我的头在旋转。 我现在意识到我做错了是有另一个方法/属性来返回我的任务。 我应该做的是从我的任务中获得一个新的类inhrite。 在那里,我可以轻松获取类名并将字符串保存到db中,然后再退回并调用。

数据库是否是必需的?

如果没有,那么Windows计划任务(他们倾向于“正常工作”)会调用一般控制台应用程序。 控制台应用程序的参数可以是:

  • 包含要执行的任务的DLL
  • 实现您定义的接口的类的名称
  • 其他论点

这样,您可以将所有任务放入一个或多个任务中。 或者,您可以创建一个属性,将该属性应用于您的任务以为其提供“友好名称”,并对程序集使用reflection来查找具有匹配属性的类。

编辑:示例:

 interface ITask { void Execute(ExcecutionContext context); } [TaskName("Send Emails") class SendEmailsTask : ITask { public void Execute(ExcecutionContext context) { // Send emails. ExecutionContext might contain a dictionary of // key/value pairs for additional arguments needed for your task. } } class TaskExecuter { public void ExecuteTask(string name) { // "name" comes from the database entry var types = Assembly.GetExecutingAssembly().GetTypes(); foreach (var type in types) { // Check type.GetCustomAttributes for the TaskAttribute, then check the name } } } 

编辑2:这是对您的代码示例的回答。

 class YourClass { public static Task SendIncompleteNotification { get { return new Task( s => Console.WriteLine("Executing task... arguments: {0}", s), "My task"); } } } interface ITask { void Execute(object o); } class Task : ITask { public Task(Action action, string name) { Action = action; } public string Name { get; set; } public Action Action { get; set; } void ITask.Execute(object o) { Action((T)o); } } class Program { static void Main(string[] args) { // Assume that this is what is stored in the database var typeName = typeof (YourClass).FullName; var propertyName = "SendIncompleteNotification"; var arguments = "some arguments"; // Execute the task var type = Type.GetType(typeName); var property = type.GetProperty(propertyName); var task = (ITask)property.GetValue(null, null); task.Execute(arguments); Console.ReadKey(); } } 

您可能希望查看Windows Workflow。 据我所知,它们专为长时间运行的进程而设计,可以持久保存到数据库并在事件或计时器上唤醒。

存储程序集FullName,并键入FullName和方法名称。 假设方法签名是可预测的(比如没有参数并且返回void)

1)使用Assembly类型的静态LoadFrom方法创建程序集的实例。

2)使用GetType方法从程序集中获取类类型的引用

3)使用GetMethod方法从类型中获取MethodInfo实例

4)使用Activator.CreateInstance创建该类型的实例

5)使用MethodInfo实例的Invoke执行方法,从步骤4传入类实例。(抱歉,我在没有VS副本的公共计算机上创建实际代码,但这5个步骤可以。

此外,如果您正在使用SQL 2005,请考虑使用SqlDependency对象并在您的talbe更改而不是轮询时获得“通知”。

你看过Quartz ,它运行得很好,我很确定它可以实现你需要的所有function。