Posted on 5/1/2008 1:36:33 PM
in #Silverlight
Often in a Silverlight client you will need to delay the execution of a particular action. There is no intrinsic setTimeout function like in JavaScript window object but you can use System.Windows.Threading.DispatcherTimer object. If you are looking for a tidy wrapper around this object you may want to consider this solution: public static class UIHelper
{
public static void SetTimeout(int milliseconds, Action func)
{
var timer = new DispatcherTimerContainingAction
{
Interval = new TimeSpan(0, 0, 0, 0, milliseconds),
Action = func
};
timer.Tick += _onTimeout;
timer.Start();
}
private static void _onTimeout(object sender, EventArgs arg)
{
var t = sender as DispatcherTimerContainingAction;
t.Stop();
t.Action();
t.Tick -= _onTimeout;
}
}
public class DispatcherTimerContainingAction : System.Windows.Threading.DispatcherTimer
{
/// <summary>
/// uncomment this to see when the DispatcherTimerContainingAction is collected
/// if you remove t.Tick -= _onTimeout; line from _onTimeout method
/// you will see that the timer is never collected
/// </summary>
//~DispatcherTimerContainingAction()
//{
// throw new Exception("DispatcherTimerContainingAction is disposed");
//}
public Action Action { get; set; }
}
Here is an example of how to use it to show an alert box after two seconds. UIHelper.SetTimeout(2000, () =>{
// do something here for example show alert box:
HtmlPage.Window.Alert("2 seconds have passed");
});
As you can see it looks almost like window.setTimeout in JavaScript
Initially I had it without removing the event handler and this way the delegate reference was preventing the garbage collection of the timer. But after a comment from Zi Han (Thanks Zi!) I realized it was not the right way. If you want to be sure that now it is garbage collected you can uncomment the destructor.
Share this post:
digg
Stumble Upon
del.icio.us
E-mail
|
Pierre
Posted on 5/13/2008 1:21:16 PM
And you can probably use lambda expression with that?
|
Vladimir Bodurov
Posted on 5/13/2008 1:42:55 PM
Yes absolutely, for example
UIHelper.SetTimeout(500, () => HtmlPage.Window.Alert("test"));
|
Zi Han
Posted on 12/18/2008 3:02:32 AM
Thanks for this piece of code. One question - is there a need to somehow "dispose" of the timer after it has been used.. for memory management purposes?
|
Vladimir Bodurov
Posted on 12/18/2008 3:17:55 AM
Thank you Zi, you are right we have to add the removal of the delegate. The code is now updated accordingly
|
Geoff McGrath
Posted on 5/7/2009 2:00:36 AM
window.setTimeout returns an integer -- you can use that with window.clearTimeout( int value ) to cancel a timer...I imagine this could be done using the GetHashCode...use that as a key in a dictionary, something like this:
private static Dictionary<int,DispatcherTimerContainingAction> m_Timers;
If you have SetTimeout return an int, and implement a ClearTimeout method that takes an int...wouldn't that do the trick?
|
Vladimir Bodurov
Posted on 5/7/2009 8:23:28 AM
for sure, the only issue is that I expect it will be more resource intense than the solution internal to Silverlight because you'd have to go through the JavaScript - Silverlight bridge each time
|
Geoff McGrath
Posted on 5/7/2009 1:50:28 PM
Oh...My thought was to do it within Silverlight, here's the code within your solution:
public static class UIHelper
{
private static Dictionary<int,DispatcherTimerContainingAction> m_Timers;
// static constructor
static UIHelper()
{
m_Timers = new Dictionary<int,DispatcherTimerContainingAction>();
}
public static int SetTimeout(int milliseconds, Action func)
{
int timerKey = new Random().Next(0,1000000);
var timer = new DispatcherTimerContainingAction
{
Interval = new TimeSpan(0, 0, 0, 0, milliseconds),
Action = func,
};
m_Timers.Add( timer.GetHashCode(), timer );
timer.Tick += _onTimeout;
timer.Start();
return timer.GetHashCode();
}
public static bool ClearTimeout( int TimerHashCode )
{
bool retVal = false;
try
{
DispatcherTimerContainingAction timer = m_Timers[TimerHashCode];
timer.Stop();
timer.Action = null;
timer.Tick -= _onTimeout;
if( m_Timers.Remove(TimerHashCode) )
{
retVal = true;
}
timer = null;
}
catch(KeyNotFoundException)
{
}
return retVal;
}
private static void _onTimeout(object sender, EventArgs arg)
{
var t = sender as DispatcherTimerContainingAction;
try
{
m_Timers.Remove(t.GetHashCode());
}
catch(ArgumentNullException)
{
}
t.Stop();
t.Action();
t.Tick -= _onTimeout;
}
}
public class DispatcherTimerContainingAction : System.Windows.Threading.DispatcherTimer
}
|
Vladimir Bodurov
Posted on 5/7/2009 3:30:07 PM
Ah OK, I didn't understand you at first.
If you need to cancel it, then that seems as a reasonable solution. Thanks for sharing the code!
|
Franck
Posted on 5/19/2010 7:18:16 PM
i just wanna say thank you for posting this code...
i had a problem for a game that i m developping for the windows phone and the color was always late... so i had to delay a function ...
thank you again
|
Rodney
Posted on 7/16/2010 5:14:29 PM
Hi Geoff,
I am trying to use your code in the comments above to cancel timers - I use it to show a popup window (which has a close button) and I want to cancel the event if it is closed.
I am using the tag property of the window to store it's hashcode eg.
mainPage.windowAppMessages.Tag = UITimer.SetTimeout(secondsToShow * 1000, () =>
I then pass this back in to the cancel event to close it - but I am getting some strange results/browser crashes - does this sound ok?
Thanks!
|
Manjunatha S
Posted on 8/25/2010 3:44:06 AM
Hey,
Thanks for this code .. It helped me for my development
|
Rams
Posted on 11/13/2010 7:11:53 AM
Vladimir,
Thanks for the tip. Just what I was looking for.
Geoff,
thanks for the additions.
|
D rake
Posted on 11/23/2010 11:22:07 AM
Pretty simple code , i`m looking forword for more tutorials sir.
|
bcm software
Posted on 4/18/2011 6:48:19 AM
Thanks for the tutorial on how to delay an action when using Silverlight. I have come across this problem many times and did not know how to work around it. I never knew about the System.Windows.Threading.DispatcherTimer object. I have a feeling I will be using this a lot in my upcoming projects.
|
Tarek
Posted on 7/5/2011 6:59:29 PM
|