任务调度器


  任务调度器 ITaskScheduler 接口提供了运行作业的方法。


1、获得实例

  要使用任务调度器,首先得获取到它的实例。我们不推荐使用 new 构造一个实例,而是使用 TaskSchedulerFactory 工厂类来创建一个实例。该工厂类提供一个 CreateScheduler 方法,可以接收一个 configName 参数,这个参数对应任务调度器配置(可参考 配置与扩展)中配置项的名称,如果未配置任务调度器配置项,则返回默认的任务调度器单例。如下所示:

[TestMethod]
public void TestCreateScheduler()
{
    var scheduler = TaskSchedulerFactory.CreateScheduler();
    Assert.IsNotNull(scheduler); // DefaultTaskScheduler
}

  在使用 IOC 的环境中,也可以通过构造注入或属性注入得到 ITaskScheduler 的实例。如下所示:

public class HomeController : Controller
{
    private readonly ITaskScheduler _scheduler;

    public HomeController(ITaskScheduler scheduler)
    {
        _scheduler = scheduler;
    }
}

2、使用方法

  ITaskScheduler 接口有以下两个方法:

  • StartExecutor 方法启动一个同步的任务执行器。
  • StartExecutorAsync 方法启动一个异步的任务执行器。

这两个方法都是泛型方法,泛型参数只要实现 ITaskExecutorIAsyncTaskExecutor 接口即可。如下所示:

[TestMethod]
public class StartExecutor()
{
    var scheduler = TaskSchedulerFactory.CreateScheduler();

    var option1 = new StartOptions<SampleExecutor>(TimeSpan.Zero, TimeSpan.FromSeconds(30));
    scheduler.StartExecutor<SampleExecutor>(option1);

    var option2 = new StartOptions<AsyncSampleExecutor>(TimeSpan.Zero, TimeSpan.FromSeconds(30));
    option2.Arguments.Add("name", "fireasy"); //添加参数
    scheduler.StartExecutorAsync<AsyncSampleExecutor>(option2);
}

public class SampleExecutor : ITaskExecutor
{
    public void Execute(TaskExecuteContext context)
    {
        Console.WriteLine(DateTime.Now);
    }
}

public class AsyncSampleExecutor : IAsyncTaskExecutor
{
    public async Task ExecuteAsync(TaskExecuteContext context)
    {
        Console.WriteLine(DateTime.Now);
        Console.WriteLine(context.Arguments["name"]);
    }
}

  StartOptions<T> 参数除了使用 Arguments 属性传递参数外,还可以使用 Initializer 属性,它是一个委托,用于执行器初始时对实例进行处理,比如设置属性等等。如下所示:

[TestMethod]
public class StartExecutor()
{
    var scheduler = TaskSchedulerFactory.CreateScheduler();

    var option = new StartOptions<SampleExecutor>(TimeSpan.Zero, TimeSpan.FromSeconds(30));
    option.Initializer = s => s.Name = "fireasy";
    scheduler.StartExecutor<SampleExecutor>(option);
}

public class SampleExecutor : ITaskExecutor
{
    public string Name { get; set; }

    public void Execute(TaskExecuteContext context)
    {
        Console.WriteLine(Name);
    }
}
  • Start 方法启动一个同步的委托。
  • StartAsync 方法启动一个异步的委托。

  这两个方法不需要实现 ITaskExecutorIAsyncTaskExecutor 接口,只需要提供一个委托即可。如下所示:

[TestMethod]
public class StartExecutor()
{
    var scheduler = TaskSchedulerFactory.CreateScheduler();
    scheduler.Start(new StartOptions(TimeSpan.FromSeconds(5), TimeSpan.Zero), sp =>
    {
        Console.WriteLine(DateTime.Now);
    });

    scheduler.StartAsync(new StartOptions(TimeSpan.FromSeconds(5), TimeSpan.Zero), (sp, cancel) =>
    {
        return Task.Run(() => { Console.WriteLine(DateTime.Now); });
    });
}

  执行器的构造函数支持 DI 注入,你可以使用 IOC 中的对象,或是直接使用 IServiceProvider 来获取对应的实例。另外,TaskExecuteContext 参数中也有 IServiceProvider 对象,你也可以在方法里注入对象。如下所示:

public class SampleExecutor : ITaskExecutor
{
    private readonly ICacheManager _cacheManager;

    public SampleExecutor(ICacheManager cacheManager)
    {
        _cacheManager = cacheManager;
    }

    public string Name { get; set; }

    public void Execute(TaskExecuteContext context)
    {
        var cacheManager = context.ServiceProvider.GetService<ICacheManager>();
        Assert.IsTrue(_cacheManager == cacheManager);
    }
}

3、任务运行器

  ITaskRunner 接口用来运行任务,它的 Start 方法一般用于启动一个定时器,而 Stop 方法则是停止定时器。默认的运行器是 DefaultTaskRunnerDefaultAsyncTaskRunner 类,你可以自己定义一个运行器。