I’m using following code to call Method B after N seconds method A is called. If method A
is called again within the N seconds timeout, i have to reset the time counting back to N seconds.
I cannot reference System.Windows.Form in my project, so I cannot use System.Windows.Form.Timer.
The method B must be called in the same thread A is called.
private void InitTimer()
{
timer = new BackgroundWorker();
timer.WorkerSupportsCancellation = true;
timer.WorkerReportsProgress = true;
timer.DoWork += delegate(object sender, DoWorkEventArgs e)
{
var st = DateTime.Now;
while (DateTime.Now.Subtract(st).TotalSeconds < 10)
{
if (timer.CancellationPending)
{
e.Cancel = true;
return;
}
}
};
timer.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
{
if (!e.Cancelled)
{
MethodB();
}
else
{
timer.RunWorkerAsync();
}
};
}
public void MethodA()
{
if (timer.IsBusy)
timer.CancelAsync();
else
timer.RunWorkerAsync();
}
public void MethodB()
{
//do some stuff
}
Actually the code work, but i think it’s a bit confounding. Do you know if there is a best practices to achieve the same result?
It’s a shame you’re stuck on .NET 2.0, because Rx extensions has a
Throttlemethod that achieves this effect quite elegantly.Sadly Rx requires at least .NET 3.5 SP1.
Oh well! You can always use a
System.Threading.Timerto get this done instead. Synchronization can be provided by leveraging the currentSynchronizationContext(this is whatBackgroundWorkerdoes).Here’s a sketch of a
LaggedMethodPairclass to illustrate this approach. The class takes three inputs in its constructor: anActionto be performed on-demand, anotherActionto serve as the callback that will be invoked when a given timeout has elapsed, and, of course, the timeout itself:I wrote a sample Windows Forms app to show this class in action. The form contains a
LaggedMethodPairmember with a timeout of 2000 ms. ItsprimaryActionadds an item to a list view. ItslaggedCallbackadds a highlighted item to the list view.You can see that the code runs as expected.