Task <T>中的单线程计时器和/或间隔

Sea*_*man 2 .net c# scheduling timer task-parallel-library

我想在一个任务内部的间隔上运行一个函数.就像是,

       Task t = Task.Factory.StartNew(() => {
            while (notCanceled()) {
                doSomething();
                Thread.Sleep(interval); 
            }
        }); 
Run Code Online (Sandbox Code Playgroud)

在这里使用Thread.Sleep()是一个坏主意吗?任务是长时间运行的,睡眠时间也可能很长(几分钟,甚至几小时).

一种替代方法是使用System.Timers.Timer或System.Threading.Timer.但是这两个都会导致产生额外的线程(Elapsed事件发生在新的线程池线程上).因此,对于每个重复任务,将有2个线程而不是1.任务已经是异步的,所以我不希望以这种方式使事情复杂化.

另一种行为相似的方式是使用ManualResetEvent,

    ManualResetEvent m = new ManualResetEvent(false);

    void sleep(int milliseconds)
    {
        m.WaitOne(milliseconds);
    } 
Run Code Online (Sandbox Code Playgroud)

由于永远不会调用m.Set(),因此它总是等待适当的时间,也是单线程的.这是否比Thread.Sleep()有任何明显的优势?

想知道这里最好的做法是什么.

思考?

Ser*_*rvy 5

如果您使用的是C#5.0,则可以使用:

while(notCanceled())
{
    doSomething();
    await Task.Delay(interval);
}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是早期版本,最好的选择可能是使用Timer.

您显示的两个代码示例都涉及其中一个Thread.Sleep或一个ManualResetEvent阻塞当前线程的持续时间,这意味着您的代码正在占用一个线程,该线程在您的任务被取消之前无法执行任何其他操作.你不想那样做.如果您使用计时器或await上面提到的代码,您将在等待时最终不会阻塞任何线程,然后只有在您正在进行高效工作时才会耗尽线程池的时间.