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

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

问题描述

我是新来的.NET 4.0的任务,我是不是能找到什么,我认为将是一个基于任务更​​换或实施一个定时器,如周期性的任务。有没有这样的事?

更新 我想出了什么,我认为这是一个解决方案,我需要的是包内的任务的定时器功能与子任务的的CancellationToken所有趁着并返回任务才能够参与进一步的工作步骤。

 公共静态任务StartPeriodicTask(行动行动,诠释intervalInMilliseconds,诠释delayInMilliseconds,的CancellationToken cancelToken)
{
    行动wrapperAction =()=>
    {
        如果(cancelToken.IsCancellationRequested){返回; }

        行动();
    };

    行动mainAction =()=>
    {
        TaskCreationOptions attachedToParent = TaskCreationOptions.AttachedToParent;

        如果(cancelToken.IsCancellationRequested){返回; }

        如果(delayInMilliseconds大于0)
            Thread.sleep代码(delayInMilliseconds);

        而(真)
        {
            如果(cancelToken.IsCancellationRequested){打破; }

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

            如果(cancelToken.IsCancellationRequested || intervalInMilliseconds == Timeout.Infinite){打破; }

            Thread.sleep代码(intervalInMilliseconds);
        }
    };

    返回Task.Factory.StartNew(mainAction,cancelToken);
}
 

解决方案

艾米回答,也没有基于任务周期性/定时执行。但是,根据我的原始更新,我们已经演变成一些非常有用和生产测试这一点。想到我会分享:

 使用系统;
使用System.Diagnostics程序;
使用的System.Threading;
使用System.Threading.Tasks;

命名空间ConsoleApplication7
{
    类节目
    {
        静态无效的主要(字串[] args)
        {
            任务perdiodicTask = PeriodicTaskFactory.Start(()=>
            {
                Console.WriteLine(DateTime.Now);
            },intervalInMilliseconds:2000,//火每隔两秒......
               maxIterations:10); //为总共10次迭代...

            perdiodicTask.ContinueWith(_ =>
            {
                Console.WriteLine(完了!);
            })。等待();
        }
    }

    ///<总结>
    ///工厂类来创建一个周期性的任务,以模拟<见CREF =System.Threading.Timer/>使用<看到CREF =任务>任务< /看>
    ///< /总结>
    公共静态类PeriodicTaskFactory
    {
        ///<总结>
        ///启动周期性任务。
        ///< /总结>
        ///<参数名称=行动>该动作< /参数>
        ///< PARAM NAME =intervalInMilliseconds>以毫秒为单位的时间间隔< /参数>
        ///< PARAM NAME =delayInMilliseconds>以毫秒为单位的延迟,即多长时间等待开球的定时器和LT; /参数>
        ///&所述; PARAM NAME =持续时间>将持续时间。
        ///&其中;示例>如果该持续时间被设置为10秒,这个任务被允许运行的最大时间为10秒-1。/示例>&所述; /参数>
        ///< PARAM NAME =maxIterations>最大迭代< /参数>
        ///< PARAM NAME =同步>如果设置到< C>真< / c取代;执行每个周期在阻塞时尚和每次定期执行的任务的
        ///被包括在任务的总持续时间和所述; /参数>
        ///< PARAM NAME =cancelToken>取消令牌LT; /参数>
        ///< PARAM NAME =periodicTaskCreationOptions><见CREF =TaskCreationOptions/>用于创建执行的&lt任务;见CREF =动作/>< /参数>
        ///<返回>在<见CREF =任务/>< /回报>
        ///<说明>
        ///发生在&lt例外; paramref名称=动作/>需要在动作本身进行处理。这些异常将不
        ///鼓泡到周期性任务。
        ///< /说明>
        公共静态任务开始(动作的动作,
                                 INT intervalInMilliseconds = Timeout.Infinite,
                                 INT delayInMilliseconds = 0,
                                 INT持续时间= Timeout.Infinite,
                                 INT maxIterations = -1,
                                 布尔同步=假​​,
                                 的CancellationToken cancelToken =新的CancellationToken()
                                 TaskCreationOptions periodicTaskCreationOptions = TaskCreationOptions.None)
        {
            秒表秒表=新的秒表();
            行动wrapperAction =()=>
            {
                CheckIfCancelled(cancelToken);
                行动();
            };

            行动mainAction =()=>
            {
                MainPeriodicTaskAction(intervalInMilliseconds,delayInMilliseconds,持续时间,maxIterations,cancelToken,秒表,同步,wrapperAction,periodicTaskCreationOptions);
            };

            返回Task.Factory.StartNew(mainAction,cancelToken,TaskCreationOptions.LongRunning,TaskScheduler.Current);
        }

        ///<总结>
        ///电源周期性任务操作。
        ///< /总结>
        ///< PARAM NAME =intervalInMilliseconds>以毫秒为单位的时间间隔< /参数>
        ///< PARAM NAME =delayInMilliseconds>以毫秒为单位的延迟< /参数>
        ///< PARAM NAME =持续时间>在持续时间LT; /参数>
        ///< PARAM NAME =maxIterations>最大迭代< /参数>
        ///< PARAM NAME =cancelToken>取消令牌LT; /参数>
        ///< PARAM NAME =秒表>的秒表< /参数>
        ///< PARAM NAME =同步>如果设置到< C>真< / c取代;执行每个周期在阻塞时尚和每次定期执行的任务的
        ///被包括在任务的总持续时间和所述; /参数>
        ///< PARAM NAME =wrapperAction>在包装动作< /参数>
        ///< PARAM NAME =periodicTaskCreationOptions><见CREF =TaskCreationOptions/>用于创建一个子任务执行的<看到CREF =动作/>< /参数>
        私有静态无效MainPeriodicTaskAction(INT intervalInMilliseconds,
                                                   INT delayInMilliseconds,
                                                   INT持续时间,
                                                   INT maxIterations,
                                                   的CancellationToken cancelToken,
                                                   秒表秒表,
                                                   布尔同步,
                                                   行动wrapperAction,
                                                   TaskCreationOptions periodicTaskCreationOptions)
        {
            TaskCreationOptions subTaskCreationOptions = TaskCreationOptions.AttachedToParent | periodicTaskCreationOptions;

            CheckIfCancelled(cancelToken);

            如果(delayInMilliseconds大于0)
            {
                Thread.sleep代码(delayInMilliseconds);
            }

            如果(maxIterations == 0){返回; }

            INT迭代= 0;

            ////////////////////////////////////////////////// //////////////////////////
            //使用ManualResetEventSlim因为它是在小的间隔更有效。
            //在其中较长的时间间隔中使用的情况下,它会自动地使用
            //一个标准的WaitHandle ....
            //看到http://msdn.microsoft.com/en-us/library/vstudio/5hbefs30(v=vs.100).aspx
            使用(ManualResetEventSlim periodResetEvent =新ManualResetEventSlim(假))
            {
                ////////////////////////////////////////////////// //////////
                //主周期的逻辑。通过这个模块基本上循环
                //执行操作
                而(真)
                {
                    CheckIfCancelled(cancelToken);

                    任务子任务= Task.Factory.StartNew(wrapperAction,cancelToken,subTaskCreationOptions,TaskScheduler.Current);

                    如果(同步)
                    {
                        stopWatch.Start();
                        尝试
                        {
                            subTask.Wait(cancelToken);
                        }
                        抓{/ *不要让一个错误的子任务杀周期性任务... * /}
                        stopWatch.Stop();
                    }

                    //使用相同的超时设置为System.Threading.Timer,无限超时将只执行一次迭代。
                    如果(intervalInMilliseconds == Timeout.Infinite){打破; }

                    迭代++;

                    如果(maxIterations大于0&安培;&安培;迭代> = maxIterations){打破; }

                    尝试
                    {
                        stopWatch.Start();
                        periodResetEvent.Wait(intervalInMilliseconds,cancelToken);
                        stopWatch.Stop();
                    }
                    最后
                    {
                        periodResetEvent.Reset();
                    }

                    CheckIfCancelled(cancelToken);

                    如果(持续时间大于0&安培;&安培; stopWatch.ElapsedMilliseconds> =持续时间){打破; }
                }
            }
        }

        ///<总结>
        ///检查是否取消。
        ///< /总结>
        ///< PARAM NAME =cancelToken>取消令牌LT; /参数>
        私有静态无效CheckIfCancelled(的CancellationToken的CancellationToken)
        {
            如果(的CancellationToken == NULL)
                抛出新ArgumentNullException(的CancellationToken);

            cancellationToken.ThrowIfCancellationRequested();
        }
    }
}
 

输出:

 二○一三年二月十八日下午4时17分13秒
2013年2月18日下午4时17分15秒
2013年2月18日下午4时17分十七秒
2013年2月18日下午4时17分19秒
2013年2月18日下午4点17分21秒
2013年2月18日下午四时17分23秒
2013年2月18日下午4时17分25秒
2013年2月18日下午四时17分27秒
2013年2月18日下午四点17分29秒
2013年2月18日下午4时17分31秒
完成!
preSS任意键继续。 。 。
 

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?

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);
}      

解决方案

As Amy answered, there is no Tasked based periodic/timer implementation. However, based upon my original UPDATE, we have evolved this into something quite useful and production tested. Thought I would share:

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication7
{
    class Program
    {
        static void Main(string[] args)
        {
            Task perdiodicTask = PeriodicTaskFactory.Start(() =>
            {
                Console.WriteLine(DateTime.Now);
            }, intervalInMilliseconds: 2000, // fire every two seconds...
               maxIterations: 10);           // for a total of 10 iterations...

            perdiodicTask.ContinueWith(_ =>
            {
                Console.WriteLine("Finished!");
            }).Wait();
        }
    }

    /// <summary>
    /// Factory class to create a periodic Task to simulate a <see cref="System.Threading.Timer"/> using <see cref="Task">Tasks.</see>
    /// </summary>
    public static class PeriodicTaskFactory
    {
        /// <summary>
        /// Starts the periodic task.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="intervalInMilliseconds">The interval in milliseconds.</param>
        /// <param name="delayInMilliseconds">The delay in milliseconds, i.e. how long it waits to kick off the timer.</param>
        /// <param name="duration">The duration.
        /// <example>If the duration is set to 10 seconds, the maximum time this task is allowed to run is 10 seconds.</example></param>
        /// <param name="maxIterations">The max iterations.</param>
        /// <param name="synchronous">if set to <c>true</c> executes each period in a blocking fashion and each periodic execution of the task
        /// is included in the total duration of the Task.</param>
        /// <param name="cancelToken">The cancel token.</param>
        /// <param name="periodicTaskCreationOptions"><see cref="TaskCreationOptions"/> used to create the task for executing the <see cref="Action"/>.</param>
        /// <returns>A <see cref="Task"/></returns>
        /// <remarks>
        /// Exceptions that occur in the <paramref name="action"/> need to be handled in the action itself. These exceptions will not be 
        /// bubbled up to the periodic task.
        /// </remarks>
        public static Task Start(Action action,
                                 int intervalInMilliseconds = Timeout.Infinite,
                                 int delayInMilliseconds = 0,
                                 int duration = Timeout.Infinite,
                                 int maxIterations = -1,
                                 bool synchronous = false,
                                 CancellationToken cancelToken = new CancellationToken(),
                                 TaskCreationOptions periodicTaskCreationOptions = TaskCreationOptions.None)
        {
            Stopwatch stopWatch = new Stopwatch();
            Action wrapperAction = () =>
            {
                CheckIfCancelled(cancelToken);
                action();
            };

            Action mainAction = () =>
            {
                MainPeriodicTaskAction(intervalInMilliseconds, delayInMilliseconds, duration, maxIterations, cancelToken, stopWatch, synchronous, wrapperAction, periodicTaskCreationOptions);
            };

            return Task.Factory.StartNew(mainAction, cancelToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
        }

        /// <summary>
        /// Mains the periodic task action.
        /// </summary>
        /// <param name="intervalInMilliseconds">The interval in milliseconds.</param>
        /// <param name="delayInMilliseconds">The delay in milliseconds.</param>
        /// <param name="duration">The duration.</param>
        /// <param name="maxIterations">The max iterations.</param>
        /// <param name="cancelToken">The cancel token.</param>
        /// <param name="stopWatch">The stop watch.</param>
        /// <param name="synchronous">if set to <c>true</c> executes each period in a blocking fashion and each periodic execution of the task
        /// is included in the total duration of the Task.</param>
        /// <param name="wrapperAction">The wrapper action.</param>
        /// <param name="periodicTaskCreationOptions"><see cref="TaskCreationOptions"/> used to create a sub task for executing the <see cref="Action"/>.</param>
        private static void MainPeriodicTaskAction(int intervalInMilliseconds,
                                                   int delayInMilliseconds,
                                                   int duration,
                                                   int maxIterations,
                                                   CancellationToken cancelToken,
                                                   Stopwatch stopWatch,
                                                   bool synchronous,
                                                   Action wrapperAction,
                                                   TaskCreationOptions periodicTaskCreationOptions)
        {
            TaskCreationOptions subTaskCreationOptions = TaskCreationOptions.AttachedToParent | periodicTaskCreationOptions;

            CheckIfCancelled(cancelToken);

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

            if (maxIterations == 0) { return; }

            int iteration = 0;

            ////////////////////////////////////////////////////////////////////////////
            // using a ManualResetEventSlim as it is more efficient in small intervals.
            // In the case where longer intervals are used, it will automatically use 
            // a standard WaitHandle....
            // see http://msdn.microsoft.com/en-us/library/vstudio/5hbefs30(v=vs.100).aspx
            using (ManualResetEventSlim periodResetEvent = new ManualResetEventSlim(false))
            {
                ////////////////////////////////////////////////////////////
                // Main periodic logic. Basically loop through this block
                // executing the action
                while (true)
                {
                    CheckIfCancelled(cancelToken);

                    Task subTask = Task.Factory.StartNew(wrapperAction, cancelToken, subTaskCreationOptions, TaskScheduler.Current);

                    if (synchronous)
                    {
                        stopWatch.Start();
                        try
                        {
                            subTask.Wait(cancelToken);
                        }
                        catch { /* do not let an errant subtask to kill the periodic task...*/ }
                        stopWatch.Stop();
                    }

                    // use the same Timeout setting as the System.Threading.Timer, infinite timeout will execute only one iteration.
                    if (intervalInMilliseconds == Timeout.Infinite) { break; }

                    iteration++;

                    if (maxIterations > 0 && iteration >= maxIterations) { break; }

                    try
                    {
                        stopWatch.Start();
                        periodResetEvent.Wait(intervalInMilliseconds, cancelToken);
                        stopWatch.Stop();
                    }
                    finally
                    {
                        periodResetEvent.Reset();
                    }

                    CheckIfCancelled(cancelToken);

                    if (duration > 0 && stopWatch.ElapsedMilliseconds >= duration) { break; }
                }
            }
        }

        /// <summary>
        /// Checks if cancelled.
        /// </summary>
        /// <param name="cancelToken">The cancel token.</param>
        private static void CheckIfCancelled(CancellationToken cancellationToken)
        {
            if (cancellationToken == null)
                throw new ArgumentNullException("cancellationToken");

            cancellationToken.ThrowIfCancellationRequested();
        }
    }
}

Output:

2/18/2013 4:17:13 PM
2/18/2013 4:17:15 PM
2/18/2013 4:17:17 PM
2/18/2013 4:17:19 PM
2/18/2013 4:17:21 PM
2/18/2013 4:17:23 PM
2/18/2013 4:17:25 PM
2/18/2013 4:17:27 PM
2/18/2013 4:17:29 PM
2/18/2013 4:17:31 PM
Finished!
Press any key to continue . . .

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

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