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;
}
}
}
答案 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);
...