System.Threading.Timer 是否有基于任务的替代品? [英] Is there a Task based replacement for System.Threading.Timer?

查看:20
本文介绍了System.Threading.Timer 是否有基于任务的替代品?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 .Net 4.0 的 Tasks 的新手,我无法找到我认为是基于 Task 的替换或 Timer 的实现,例如一个周期性的任务.有这种事吗?

I'm new to .Net 4.0's Tasks and I wasn't able to find what I thought would be a Task based replacement or implementation of a Timer, e.g. a periodic Task. Is there such a thing?

更新我想出了我认为是满足我需求的解决方案,即将计时器"功能包装在带有子任务的任务中,所有子任务都利用 CancellationToken 并返回任务以便能够参与进一步的任务步骤.

Update I came up with what I think is a solution to my needs which is to wrap the "Timer" functionality inside a Task with child Tasks all taking advantage of the CancellationToken and returns the Task to be able to participate in further Task steps.

public static Task StartPeriodicTask(Action action, int intervalInMilliseconds, int delayInMilliseconds, CancellationToken cancelToken)
{ 
    Action wrapperAction = () =>
    {
        if (cancelToken.IsCancellationRequested) { return; }

        action();
    };

    Action mainAction = () =>
    {
        TaskCreationOptions attachedToParent = TaskCreationOptions.AttachedToParent;

        if (cancelToken.IsCancellationRequested) { return; }

        if (delayInMilliseconds > 0)
            Thread.Sleep(delayInMilliseconds);

        while (true)
        {
            if (cancelToken.IsCancellationRequested) { break; }

            Task.Factory.StartNew(wrapperAction, cancelToken, attachedToParent, TaskScheduler.Current);

            if (cancelToken.IsCancellationRequested || intervalInMilliseconds == Timeout.Infinite) { break; }

            Thread.Sleep(intervalInMilliseconds);
        }
    };

    return Task.Factory.StartNew(mainAction, cancelToken);
}      

推荐答案

这取决于 4.5,但这有效.

It depends on 4.5, but this works.

public class PeriodicTask
{
    public static async Task Run(Action action, TimeSpan period, CancellationToken cancellationToken)
    {
        while(!cancellationToken.IsCancellationRequested)
        {
            await Task.Delay(period, cancellationToken);

            if (!cancellationToken.IsCancellationRequested)
                action();
        }
     }

     public static Task Run(Action action, TimeSpan period)
     { 
         return Run(action, period, CancellationToken.None);
     }
}

显然,您可以添加一个带有参数的通用版本.这实际上类似于其他建议的方法,因为在后台 Task.Delay 使用计时器到期作为任务完成源.

Obviously you could add a generic version that takes arguments as well. This is actually similar to other suggested approaches since under the hood Task.Delay is using a timer expiration as a task completion source.

这篇关于System.Threading.Timer 是否有基于任务的替代品?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆