使用任务和ContinueWith实现调度程序

时间:2014-05-02 21:14:06

标签: c# .net task scheduler

我正在尝试编写自己的调度程序;根据延迟,其背后的理由是所有提交的行动将按顺序执行。例如,如果时间为0,我会安排延迟A的行动5,并在时间1安排行动B延迟2,然后应B首先执行3A时应执行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);

基本上,我想要做的是:

Waiter

此代码的相关测试将是:

Signal

在上面的代码中,Await是一个在构造函数中初始化了内部变量的类; _count方法递减内部变量和2方法循环(并在每次迭代时休眠10毫秒),直到内部变量小于或等于零。

测试的目的是显示已按计划执行计划的操作。

大多数时候这是真的并且测试通过了,但在很少的情况下4的结果值是{{1}}而不是{{1}}。我花了很多时间试图弄清楚为什么会发生这种情况,但我似乎无法弄明白,而且我对C#缺乏经验也没有帮助。

有人有任何建议吗?

1 个答案:

答案 0 :(得分:4)

首先,_count未与来自不同线程的访问同步。

我建议您根本不使用ContinueWith;它是一个非常低级的方法,很容易弄错细节(例如,默认调度程序是TaskScheduler.Current,这几乎不是你想要的)。您的常规逻辑代码应使用await而不是ContinueWith

关于调度程序,现在几乎不可能成为开发自己的用例的好用例。有更好的可用的天才开发和经过充分测试。考虑Reactive Extensions:它们提供了几个调度程序,它们都是support scheduling