最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin8浏览0评论

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

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;
                }
            }
        }
Share Improve this question asked Nov 9, 2016 at 8:26 KorayKoray 1,8061 gold badge28 silver badges39 bronze badges 3
  • JS hasn't timers, setTimeout and setInterval are DOM methods. – Teemu Commented Nov 9, 2016 at 8:33
  • 1 @Teemu - don't be overly-pedantic, you know what the OP meant. – user1017882 Commented Nov 9, 2016 at 9:16
  • @JᴀʏMᴇᴇ The ment was not meant overly-pedantic. Just saying, that timers are not built-in features in JavaScript. That might be useful, when trying to find similar features from other languages. – Teemu Commented Nov 9, 2016 at 9:33
Add a ment  | 

3 Answers 3

Reset to default 8

This is how I implement Javascript's setTimeout and clearTimeout functions in C# using Task Parallel Library (TPL):

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

How to use:

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

var timeout = SetTimeout(() => {

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

}, 2000);

And if you want to cancel the action before it's run:

ClearTimeout(timeout);

Libraries to use

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

The function itself

...
private void setTimeout(Func<int> function, int timeout) // Take in a callback and a timeout
{
    Task.Delay(timeout).ContinueWith((Task task) =>      // Use Task to delay the function by the timeout, then call the function "function"
    {
        function();
    });
}
...

An example on how to use it

...
setTimeout(() => 
{
    Console.WriteLine("After 1 second");
    return 0; // By the way, don't miss this line, because or else you'll get an error of not fitting in Function<int>
}, 1000);
...

Only drawback I could find so far is, if there are running actions, the application cannot exit. While ending the application this function should be called:

    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);
        }
    }
发布评论

评论列表(0)

  1. 暂无评论