html门户网站,教育机构网址,中国互联网头部企业,番禺人才网账号是什么这里记录下 TaskScheduler 的简单用法。
使用场景#xff1a;
使用 Task 的时候#xff0c;大家知道用 TaskFactory.StartNew 可以用来创建一个 Task 。这里如果创建了 3 个#xff0c;那么这3个 Task 就各自放飞直接运行了。
class Program
{private static TaskFactory…这里记录下 TaskScheduler 的简单用法。
使用场景
使用 Task 的时候大家知道用 TaskFactory.StartNew 可以用来创建一个 Task 。这里如果创建了 3 个那么这3个 Task 就各自放飞直接运行了。
class Program
{private static TaskFactory _taskFactory;static void Main(string[] args){_taskFactory new TaskFactory();_taskFactory.StartNew(Func1);_taskFactory.StartNew(Func2);_taskFactory.StartNew(Func3);Console.ReadLine();}static void Func1(){Thread.Sleep(3000);Console.WriteLine(Func1);}static void Func2(){Thread.Sleep(2000);Console.WriteLine(Func2);}static void Func3(){Thread.Sleep(1000);Console.WriteLine(Func3);}
}结果 Func3 Func2 Func1
一般情况下没什么大问题但如果这3个中的每个Task都非常耗CPU或者内存而计算机又需要预留资源去干别的事情这就要让3个Task不能同时执行。又或者确实要让某些Task先做有些后做。这就需要我们自己能够决定Task执行顺序。
怎样达到这样的效果
答案就是TaskScheduler它可以让已经创建好的 Task 去按照特殊的顺序来执行。
就拿上面的场景来举例 为了节约系统资源我要让这3个Task单独执行有一个在执行其它俩就不能执行。最简单的就是串行执行这样只需要写一个类继承TaskScheduler
public class MyTaskScheduler : TaskScheduler, IDisposable
{private static readonly object _mutex new object();public readonly ListTask _currentTasks new ListTask();private readonly ManualResetEvent[] _schedulerEvents new ManualResetEvent[2];public override int MaximumConcurrencyLevel 1;public MyTaskScheduler(){_schedulerEvents[0] new ManualResetEvent(false);_schedulerEvents[1] new ManualResetEvent(false);var executionThread new Thread(ExecutionThread) { Name MyThread };executionThread.SetApartmentState(ApartmentState.MTA);executionThread.IsBackground true;executionThread.Priority ThreadPriority.Normal;executionThread.Start(null);}public void Dispose(){_schedulerEvents[1].Set();}private void ExecutionThread(object args){try{while (true){if (!WaitIfEmpty()){break;}Task task;lock (_mutex){task _currentTasks[0];}try{TryExecuteTask(task);}catch (Exception){throw;}finally{TryDequeue(task);}}}finally{//todo}}private bool WaitIfEmpty(){lock (_mutex){if (_currentTasks.Count 0){//pause task_schedulerEvents[0].Reset();}}//wait any signal.int id WaitHandle.WaitAny(_schedulerEvents);// id is item index of _schedulerEventsreturn id 0;}protected override IEnumerableTask? GetScheduledTasks(){lock (_mutex){return _currentTasks.ToArray();}}protected override void QueueTask(Task task){lock (_mutex){_currentTasks.Add(task);if (_currentTasks.Count 0){// Start task_schedulerEvents[0].Set();}}}protected sealed override bool TryDequeue(Task task){lock (_mutex){var res _currentTasks.Remove(task);return res;}}protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued){return false;}
}运行结果 Func1 Func2 Func3
在MyTaskScheduler 中我建了一个线程 executionThread线程方法是一个while循环一直在监听有没有新的Task过来有多个Task过来就按Task创建顺序执行没有的话 while 就暂停在 waitany 处。
这样的场景配合 ManualResetEvent 和Task的CancellationTokenSource 非常适合做 带有暂停和取消功能的任务列表。