c#可靠的延迟/计划执行最佳实践
我正在从事的项目需要在特定时间执行一些任务。我不确定处理这种情况的最佳方法是什么。该方法必须能够在服务器重新启动/维护后继续使用。和方法调用必须以编程方式进行c#可靠的延迟/计划执行最佳实践,c#,scheduled-tasks,delayed-execution,C#,Scheduled Tasks,Delayed Execution,我正在从事的项目需要在特定时间执行一些任务。我不确定处理这种情况的最佳方法是什么。该方法必须能够在服务器重新启动/维护后继续使用。和方法调用必须以编程方式进行 var type = ApplicationTask.SendIncompleteNotification.GetType(); //type.Name shows "Task`1" rather than SendIncompleteNotification 我正在考虑走这条路: 我可以在数据库中有一个名为TaskTable的表(甚至
var type = ApplicationTask.SendIncompleteNotification.GetType();
//type.Name shows "Task`1" rather than SendIncompleteNotification
我正在考虑走这条路:
我可以在数据库中有一个名为TaskTable的表(甚至是一个消息队列),它可以有TaskID(PK)、TaskName(varchar)、TaskStatus(enum success、failed、scheduled)和Timeof Execution。但是我需要一个windows服务,它可以定期轮询数据库中任何未执行的任务。我面临的问题是:我使用什么作为任务名保存到数据库中?类名?类和方法名ToString?我如何转换回字符串并以编程方式调用方法调用(我不希望有一个巨大的switch语句)?典型任务如下所示。因此,我希望能够获得任务“SendIncompletNotification”的名称和类名,并将其保存到数据库中,然后通过编程进行检索调用
public static Task<string> SendIncompleteNotification
{
get
{
return new Task<string>
(
a => Console.WriteLine("Sample Task")
, "This is a sample task which does nothing."
);
}
}
有没有更好的方法来处理这种情况?谢谢
更新:
对不起,我头晕了。我现在意识到我做错的是使用另一个方法/属性来返回我的任务。我应该做的是从我的任务中继承一门新课。在那里,我可以很容易地获得类名并将字符串保存到db中,然后再返回并调用。您可能需要查看Windows工作流。据我所知,它们是为长时间运行的进程而设计的,可以持久化到数据库,并在事件或计时器时唤醒。数据库是一种需求吗 如果没有,那么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();
}
}
classyourclass
{
公共静态任务发送未完成通知
{
得到{
返回新任务(
s=>Console.WriteLine(“正在执行任务…参数:{0}”,s),
“我的任务”);
}
}
}
接口ITask
{
无效执行(对象o);
}
课堂任务:ITask
{
公共任务(操作、字符串名称)
{
行动=行动;
}
公共字符串名称{get;set;}
公共操作动作{get;set;}
void ITask.Execute(对象o)
{
作用((T)o);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
//假设这是存储在数据库中的内容
var typeName=typeof(YourClass).FullName;
var propertyName=“SendCompleteNotification”;
var arguments=“一些参数”;
//执行任务
var type=type.GetType(typeName);
var property=type.GetProperty(propertyName);
var task=(ITask)property.GetValue(null,null);
执行(参数);
Console.ReadKey();
}
}
存储程序集全名,然后键入全名和方法名。假设方法签名是可预测的(如无参数和返回void)
1) 使用程序集类型的静态LoadFrom方法创建程序集的实例
2) 使用GetType方法从程序集中获取对类类型的引用
3) 使用GetMethod方法从类型中获取MethodInfo实例
4) 使用Activator.CreateInstance创建类型的实例
5) 使用MethodInfo实例的调用执行该方法,从步骤4传入类实例。(很抱歉,我现在在一台公共计算机上,没有一份VS的副本来编写真正的代码,但这5个步骤就可以了
如果使用SQL 2005,请考虑使用SQLRe相依对象并获得“通知”当您的talbe更改而不是轮询时。
您看过了吗,它运行得很好,我很确定它实现了您需要的所有功能。很抱歉,我的头脑一直在转。我现在意识到我做错了的是使用另一个方法/属性来返回我的任务。我应该做的是从我的任务中继承一个新类。并且我的继承人可以很容易地得到类名。