【问题标题】:c# reliable delayed/scheduled execution best practicec#可靠的延迟/计划执行最佳实践
【发布时间】:2009-03-26 03:23:11
【问题描述】:

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

我正在考虑走这条路:

我可以在数据库(甚至是消息队列)中有一个名为 TaskTable 的表,它可以有 TaskID(PK)、TaskName(varchar)、TaskStatus(enum success、failed、scheduled) 和 TimeOfExecution。但我需要一个定期轮询数据库以查找任何未执行任务的 Windows 服务。我面临的问题是:我用什么作为 TaskName 来保存到数据库中?班级名称?类和方法名 ToString?我怎样才能将字符串转换回来并以编程方式调用方法调用(我不想有一个巨大的 switch 语句)?一个典型的任务如下所示。所以我需要能够获取任务“SendIncompleteNotification”的名称和类名将其保存到数据库中并在检索时以编程方式调用

public static Task<string> SendIncompleteNotification
{
  get
    {
      return new Task<string>
        (
          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

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

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

【问题讨论】:

    标签: c# scheduled-tasks delayed-execution


    【解决方案1】:

    数据库是必需的吗?

    如果不是,那么调用通用控制台应用程序的 Windows 计划任务(他们倾向于“正常工作”)怎么样。控制台应用程序的参数可能是:

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

    这样,您可以将所有任务放入一个程序集或多个程序集中。或者,您可以创建一个属性,将该属性应用到您的任务以给它们一个“友好的名称”,然后对程序集使用反射来查找具有匹配属性的类。

    编辑:示例:

    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<string> SendIncompleteNotification
        {
            get {
                return new Task<string>(
                    s => Console.WriteLine("Executing task... arguments: {0}", s),
                    "My task");
            }
        }
    }
    
    
    interface ITask
    {
        void Execute(object o);
    }
    
    class Task<T> : ITask
    {        
        public Task(Action<T> action, string name)
        {
            Action = action;
        }
    
        public string Name { get; set; }
        public Action<T> 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();
        }
    }
    

    【讨论】:

    • 对不起,我头晕目眩。我现在意识到我做错了什么是让另一种方法/属性返回我的 Task。我应该做的是从我的 Task 中继承一个新类。他们的 for i 可以很容易地得到类名。
    【解决方案2】:

    您可能想查看 Windows 工作流。据我所知,它们是为长时间运行的进程而设计的,可以持久化到数据库并在事件或计时器上唤醒。

    【讨论】:

      【解决方案3】:

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

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

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

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

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

      5) 使用 MethodInfo 实例的 Invoke 执行方法,从第 4 步传入类实例。(抱歉,我在公共计算机上没有 VS 的副本来编写真正的代码,但是这 5 个步骤会做。

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

      【讨论】:

        【解决方案4】:

        你看过Quartz吗,它工作得很好,而且我很确定它实现了你需要的所有功能。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-02-24
          • 2021-05-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-30
          相关资源
          最近更新 更多