Javascript's SetTimeout, SetInterval and ClearInterval equivalent in c#

时间:2016-11-09 08:26:27

标签: javascript c#

In many cases I need to use these functions in C#. My projects has to be .NET 4.0 and following code is the result that I was able to write after reading questions and answers about these functions. I have been using them for a while and didn't have any problems. However, playing with threads is dangerous so I have a doubt if I'm doing it wrong or not.

My question is, are these functions are safe to use; or is there a better way to do it for .NET 4.0?

        private static volatile List<System.Threading.Timer> _timers = new List<System.Threading.Timer>();
        private static object lockobj = new object();
        public static void SetTimeout(Action action, int delayInMilliseconds)
        {
            System.Threading.Timer timer = null;
            var cb = new System.Threading.TimerCallback((state) =>
            {
                lock (lockobj)
                    _timers.Remove(timer);
                timer.Dispose();
                action();
            });
            lock (lockobj)
                _timers.Add(timer = new System.Threading.Timer(cb, null, delayInMilliseconds, System.Threading.Timeout.Infinite));
        }
        private static volatile Dictionary<Guid, System.Threading.Timer> _timers2 = new Dictionary<Guid, System.Threading.Timer>();
        private static object lockobj2 = new object();
        public static Guid SetInterval(Action action, int delayInMilliseconds)
        {
            System.Threading.Timer timer = null;
            var cb = new System.Threading.TimerCallback((state) => action());
            lock (lockobj2)
            {
                Guid guid = Guid.NewGuid();
                _timers2.Add(guid, timer = new System.Threading.Timer(cb, null, delayInMilliseconds, delayInMilliseconds));
                return guid;
            }
        }
        public static bool ClearInterval(Guid guid)
        {
            lock (lockobj2)
            {
                if (!_timers2.ContainsKey(guid))
                    return false;
                else
                {
                    var t = _timers2[guid];
                    _timers2.Remove(guid);
                    t.Dispose();
                    return true;
                }
            }
        }

3 个答案:

答案 0 :(得分:1)

这是我如何使用任务并行库(TPL)在C#中实现Javascript的setTimeout和clearTimeout函数的方法:

SetTimeout:

public CancellationTokenSource SetTimeout(Action action, int millis) {

    var cts = new CancellationTokenSource();
    var ct = cts.Token;
    _ = Task.Run(() => {
        Thread.Sleep(millis);
        if (!ct.IsCancellationRequested)
            action();
    }, ct);

    return cts;
}

ClearTimeout:

public void ClearTimeout(CancellationTokenSource cts) {
    cts.Cancel();
}

使用方法:

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

var timeout = SetTimeout(() => {

    Console.WriteLine("Will be run in 2 seconds if timeout is not cleared...");

}, 2000);

如果您想在执行操作之前取消该操作:

ClearTimeout(timeout);

答案 1 :(得分:0)

到目前为止,我唯一能找到的缺点是,如果有正在运行的操作,则应用程序无法退出。在结束应用程序时,应该调用此函数:

    public static void Free()
    {
        lock (lockobj)
        {
            foreach (var t in _timers)
                t.Dispose();
            _timers.Clear();
        }
        lock (lockobj2)
        {
            foreach (var key in _timers2.Keys.ToList())
                ClearInterval(key);
        }
    }

答案 2 :(得分:0)

...
using System;
using System.Threading.Tasks;
...
...
private void setTimeout(Func<int> function, int timeout) 
{
    Task.Delay(timeout).ContinueWith((Task task) => 
    {
        function();
    });
}
...
...
setTimeout(() => 
{
    Console.WriteLine("After 1 second");
    return 0;
}, 1000);
...