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
时不指定它呢?显示实际代码,包括
服务员