大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
这里记录下 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 List<Task> _currentTasks = new List<Task>();
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 _schedulerEvents
return id == 0;
}
protected override IEnumerable<Task>? 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;
}
}
主函数中只要稍作修改:
static void Main(string[] args)
{
var taskScheduler = new MyTaskScheduler();
_taskFactory = new TaskFactory(taskScheduler);
_taskFactory.StartNew(Func1);
_taskFactory.StartNew(Func2);
_taskFactory.StartNew(Func3);
Console.ReadLine();
}
运行结果:
Func1
Func2
Func3
在MyTaskScheduler 中,我建了一个线程 executionThread,线程方法是一个while循环,一直在监听有没有新的Task过来,有多个Task过来,就按Task创建顺序执行,没有的话 while 就暂停在 waitany 处。
这样的场景,配合 ManualResetEvent 和Task的CancellationTokenSource 非常适合做 带有暂停和取消功能的任务列表。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/183039.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...