C # reliable deferred / scheduled best practice implementation

The project I'm working on requires certain accomplishments at a specific time. I am not sure what would be the best way to deal with this situation. The method should be able to withstand server restart / maintenance. And method calls must be programmatic.

I am considering moving along this path:

I could have a table in the database (or even a message queue) called TaskTable, which could have TaskID (PK), TaskName (varchar), TaskStatus (enumeration success, failed, scheduled) and TimeOfExecution. But I need a Windows service that periodically examines the database for any outstanding tasks. The problem I am facing is this: what am I using as a TaskName to save to the database? Class name? class and method name ToString? And how can I convert the string back and programmatically call method calls (I don't want to have a giant switch statement)? A typical task will look below. Thus, I could get the name of the task "SendIncompleteNotification" and the name of the class, to save it in the database, and programmatically when programmed again

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

? !

: , . , , /, . , , - , . db, .

+3
4

?

, 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();
    }
}
+3

, Windows. , , .

+3

FullName FullName . , (, )

1) , LoadFrom Assembly.

2) , GetType

3) MethodInfo GetMethod

4) , Activator.CreateInstance

5) , Invoke MethodInfo, 4. (, VS , 5 .

, SQL 2005, SqlDependency "", , .

+1

Quartz, , , .

+1

Source: https://habr.com/ru/post/1705380/


All Articles