如何在两个定时器之间创建延迟?
How to create delay between two timers?
目标
有两种方法:Add() 和 Remove()。
Add() 方法每 X 秒发生一次,直到被用户停止;添加
反对数据库;等待N秒;调用 Remove();
Remove() 方法由 Add() 方法调用并删除由添加的对象
添加() 方法。
我的代码
static bool keepGoing = true;
static System.Timers.Timer AddMethodTimer= new System.Timers.Timer();
static System.Timers.Timer RemoveMethodTimer = new System.Timers.Timer();
private static void Execute()
{
if (!keepGoing)
{
AddMethodTimer.Stop();
RemoveMethodTimer.Stop();
}
else
{
AddMethodTimer.Interval = 30; // X = 30
RemoveMethodTimer.Interval = 5; // N = 5
AddMethodTimer.Elapsed += new ElapsedEventHandler(Add);
AddMethodTimer.Start();
Thread.Sleep(RemoveMethodTimer.Interval)//In this case, N=5;
RemoveMethodTimer.Elapsed += new ElapsedEventHandler(Remove);
}
}
private static void Add(object source, ElapseEventArgs e)
{
//add operation
}
private static void Remove(object source, ElapseEventArgs e)
{
//remove operation
}
用户只能更改 "keepGoing" 变量。如果它是假的,定时器应该停止。整个代码在更改时触发(我有一个 post IActionResult 来处理它。它工作正常。当 keepGoing 被更改时,它进入我提供的代码)。
注意 : 如果对象被插入到数据库中并且用户使 keepGoing 为 false,Remove() 将不会被执行
你可以试试异步方式。这不会在您的代码中使用 'use' 计时器。通过使用 CancellationTokenSource,您也可以取消 Task.Delays。
这是举例。你应该改进它,因为如果你在 30 秒延迟内取消它,它仍然会调用添加和删除。您可以为此使用 if (!tcs.IsCancellationRequested) Add();
。随便玩玩吧。
static CancellationTokenSource tcs = new CancellationTokenSource();
private static async Task ExecuteAsync()
{
while (!tcs.IsCancellationRequested)
{
await Task.Delay(30000, tcs.Token);
Add();
await Task.Delay(5000, tcs.Token);
Remove();
}
}
private static void Stop()
{
tcs.Cancel();
}
private static void Add()
{
//add operation
}
private static void Remove()
{
//remove operation
}
坚持使用计时器,我建议这样:
private static System.Timers.Timer myTimer = null;
private static readonly syncObj = new object();
public static bool Execute( bool runTimer )
{
if(runTimer)
{
lock(syncObj) // myTimer access shall be thread safe
{
if(myTimer != null) return false;
// Timer is not active => activate
myTimer = new System.Timers.Timer();
myTimer.AutoReset = false; // 1-Time trigger!!
myTimer.Elapsed += AddOnTimer;
myTimer.Interval = TimeSpan.FromSeconds(30).TotalMilliseconds; // Interval is in ms!
myTimer.Enabled = true;
}
}
else
{
lock(syncObj)
{
if( myTimer == null ) return false;
myTimer.Enabled = false;
myTimer.Dispose();
myTimer = null;
}
}
return true;
}
private static void AddOnTimer(object sender, ElapsedEventArgs e)
{
AddObjToDB();
lock( syncObj )
{
if( myTimer == null ) return; // myTimer has been canceled, meanwhile
myTimer.Elapsed -= AddOnTimer; // Instead of Add, next time
myTimer.Elapsed += RemoveOnTimer; // execute Remove
myTimer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
myTimer.Enabled = true;
}
}
private static void RemoveOnTimer(object sender, ElapsedEventArgs e)
{
RemoveObjFromDB();
lock( syncObj )
{
if( myTimer == null ) return; // myTimer has been canceled
myTimer.Elapsed -= RemoveOnTimer; // Instead of Remove, next time
myTimer.Elapsed += AddOnTimer; // execute Add
myTimer.Interval = TimeSpan.FromSeconds(30).TotalMilliseconds;
myTimer.Enabled = true;
}
}
异步方法:
public static async Task Execute( CancellationToken cancel )
{
while( !cancel.IsCancellationRequested )
{
await Task.Delay(TimeSpan.FromSeconds(30), cancel);
await AddObjToDBAsync(cancel);
await Task.Delay(TimeSpan.FromSeconds(5), cancel);
await RemoveFromDBAsync(cancel);
}
}
private static async Task AddObjToDBAsync( CancellationToken cancel )
{
if( !cancel.IsCancellationRequested )
{
await YourDataLayer.AddAsync( someObj ); // <= I made this up, of course. "Async all the way" is recommended.
}
}
private static async Task RemoveObjFromDBAsync( CancellationToken cancel )
{
if( !cancel.IsCancellationRequested )
{
await YourDataLayer.RemoveAsync( someObj );
}
}
*(我刚刚看到,Jeroen 已经发布了一个异步方法。无论如何,我会把它留在这里。)
目标
有两种方法:Add() 和 Remove()。
Add() 方法每 X 秒发生一次,直到被用户停止;添加 反对数据库;等待N秒;调用 Remove();
Remove() 方法由 Add() 方法调用并删除由添加的对象 添加() 方法。
我的代码
static bool keepGoing = true;
static System.Timers.Timer AddMethodTimer= new System.Timers.Timer();
static System.Timers.Timer RemoveMethodTimer = new System.Timers.Timer();
private static void Execute()
{
if (!keepGoing)
{
AddMethodTimer.Stop();
RemoveMethodTimer.Stop();
}
else
{
AddMethodTimer.Interval = 30; // X = 30
RemoveMethodTimer.Interval = 5; // N = 5
AddMethodTimer.Elapsed += new ElapsedEventHandler(Add);
AddMethodTimer.Start();
Thread.Sleep(RemoveMethodTimer.Interval)//In this case, N=5;
RemoveMethodTimer.Elapsed += new ElapsedEventHandler(Remove);
}
}
private static void Add(object source, ElapseEventArgs e)
{
//add operation
}
private static void Remove(object source, ElapseEventArgs e)
{
//remove operation
}
用户只能更改 "keepGoing" 变量。如果它是假的,定时器应该停止。整个代码在更改时触发(我有一个 post IActionResult 来处理它。它工作正常。当 keepGoing 被更改时,它进入我提供的代码)。
注意 : 如果对象被插入到数据库中并且用户使 keepGoing 为 false,Remove() 将不会被执行
你可以试试异步方式。这不会在您的代码中使用 'use' 计时器。通过使用 CancellationTokenSource,您也可以取消 Task.Delays。
这是举例。你应该改进它,因为如果你在 30 秒延迟内取消它,它仍然会调用添加和删除。您可以为此使用 if (!tcs.IsCancellationRequested) Add();
。随便玩玩吧。
static CancellationTokenSource tcs = new CancellationTokenSource();
private static async Task ExecuteAsync()
{
while (!tcs.IsCancellationRequested)
{
await Task.Delay(30000, tcs.Token);
Add();
await Task.Delay(5000, tcs.Token);
Remove();
}
}
private static void Stop()
{
tcs.Cancel();
}
private static void Add()
{
//add operation
}
private static void Remove()
{
//remove operation
}
坚持使用计时器,我建议这样:
private static System.Timers.Timer myTimer = null;
private static readonly syncObj = new object();
public static bool Execute( bool runTimer )
{
if(runTimer)
{
lock(syncObj) // myTimer access shall be thread safe
{
if(myTimer != null) return false;
// Timer is not active => activate
myTimer = new System.Timers.Timer();
myTimer.AutoReset = false; // 1-Time trigger!!
myTimer.Elapsed += AddOnTimer;
myTimer.Interval = TimeSpan.FromSeconds(30).TotalMilliseconds; // Interval is in ms!
myTimer.Enabled = true;
}
}
else
{
lock(syncObj)
{
if( myTimer == null ) return false;
myTimer.Enabled = false;
myTimer.Dispose();
myTimer = null;
}
}
return true;
}
private static void AddOnTimer(object sender, ElapsedEventArgs e)
{
AddObjToDB();
lock( syncObj )
{
if( myTimer == null ) return; // myTimer has been canceled, meanwhile
myTimer.Elapsed -= AddOnTimer; // Instead of Add, next time
myTimer.Elapsed += RemoveOnTimer; // execute Remove
myTimer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
myTimer.Enabled = true;
}
}
private static void RemoveOnTimer(object sender, ElapsedEventArgs e)
{
RemoveObjFromDB();
lock( syncObj )
{
if( myTimer == null ) return; // myTimer has been canceled
myTimer.Elapsed -= RemoveOnTimer; // Instead of Remove, next time
myTimer.Elapsed += AddOnTimer; // execute Add
myTimer.Interval = TimeSpan.FromSeconds(30).TotalMilliseconds;
myTimer.Enabled = true;
}
}
异步方法:
public static async Task Execute( CancellationToken cancel )
{
while( !cancel.IsCancellationRequested )
{
await Task.Delay(TimeSpan.FromSeconds(30), cancel);
await AddObjToDBAsync(cancel);
await Task.Delay(TimeSpan.FromSeconds(5), cancel);
await RemoveFromDBAsync(cancel);
}
}
private static async Task AddObjToDBAsync( CancellationToken cancel )
{
if( !cancel.IsCancellationRequested )
{
await YourDataLayer.AddAsync( someObj ); // <= I made this up, of course. "Async all the way" is recommended.
}
}
private static async Task RemoveObjFromDBAsync( CancellationToken cancel )
{
if( !cancel.IsCancellationRequested )
{
await YourDataLayer.RemoveAsync( someObj );
}
}
*(我刚刚看到,Jeroen 已经发布了一个异步方法。无论如何,我会把它留在这里。)