C# 使用tasks和ContinueWith实现调度程序
我正在尝试编写自己的调度程序;其背后的理由是,根据延迟,所有提交的操作都将按顺序执行。例如,如果在时间C# 使用tasks和ContinueWith实现调度程序,c#,.net,task,scheduler,C#,.net,Task,Scheduler,我正在尝试编写自己的调度程序;其背后的理由是,根据延迟,所有提交的操作都将按顺序执行。例如,如果在时间0I调度动作A延迟5,在时间1I调度动作B延迟2,则B应首先在时间3执行,然后A应在时间5执行 基本上,我想做的是: public class MyScheduler { Task _task = new Task(() => { }); public MyScheduler() { _task.Start(); } p
0
I调度动作A
延迟5
,在时间1
I调度动作B
延迟2
,则B
应首先在时间3
执行,然后A
应在时间5
执行
基本上,我想做的是:
public class MyScheduler
{
Task _task = new Task(() => { });
public MyScheduler()
{
_task.Start();
}
public void Schedule(Action action, long delay)
{
Task.Delay(TimeSpan.FromTicks(delay)).ContinueWith(_ =>
lock(_task) {
_task = _task.ContinueWith(task => action())
}
);
}
}
本规范的相关测试为:
var waiter = new Waiter(3);
int _count = 0;
mysched = new MyScheduler();
mysched.Schedule(() => { _count++; waiter.Signal(); });
mysched.Schedule(() => { Task.Delay(100).Wait(); _count *= 3; waiter.Signal(); });
mysched.Schedule(() => { _count++; waiter.Signal(); });
waiter.Await();
Assert.AreEqual(4, _count);
在上面的代码中,water
是一个类,其内部变量在构造函数中初始化;信号
方法递减该内部变量,等待
方法循环(并在每次迭代中休眠10 ms),直到内部变量小于或等于零
测试的目的是显示计划的操作已按顺序执行
大多数情况下,这是正确的,测试通过,但在少数情况下,\u count
的结果值是2
,而不是4
。我花了很多时间试图弄清楚为什么会发生这种情况,但我似乎无法弄清楚,而且我缺乏C#方面的经验也无济于事
有人有什么建议吗?首先,对于不同线程的访问,
\u count
是不同步的
我建议您根本不要使用ContinueWith
;这是一种非常低级的方法,很容易获取错误的详细信息(例如,默认的调度程序是TaskScheduler.Current
,这几乎不是您想要的)。您的常规逻辑代码应该使用wait
而不是ContinueWith
关于调度程序,现在几乎不可能为开发自己的应用程序创建一个好的用例。有一些更好的是由天才开发的,并且经过了很好的测试。考虑反应性扩展:它们提供了几个调度程序,它们都是.< /p> + 1,用于建议反应式框架调度器。它们特别好。
Schedule(Action-Action,long-delay)
有一个非可选参数delay
,为什么在调用mysched.Schedule
时不指定它呢?显示实际代码,包括服务员
。