Dispatcher, Cross-Thread Property Setting & Lambda Expressions

I am finishing up my tutorial on Hyper-video and in the more advanced section I discuss the idea of displaying a button when the video’s marker is hit, and then removing the button after a short time has passed.

To make this work, I instantiate an object of type Timer and pass in the name of the (static) callback method, the button that was pressed, the length of time I want the button to be visible (in milliseconds) and the time between invocations – in this case the value Timout.Infinite to indicate that I do not want the timer to restart after it calls the callback.

 

Timer t = new Timer(
   EndShowMore,       // call back
   ShowMore,          // state
   2000,              // dueTime
   System.Threading.Timeout.Infinite   // period
   );

 

When the timer dueTime (2 seconds) passes  the callback method (EndShowMore)is invoked.

As noted, EndShowMore must be static. Its job is to make the button invisible and disabled. But the static method and the button are in different threads and so the method cannot set these properties directly.

What is needed is a dispatcher in the same thread as the controls. Fortunately, the button (ShowMore) is provided as an argument to the callback (you passed it in as the second parameter to the Timer constructor.)

Once we cast that state object back to type Button we can grab its Dispatcher and use that to call BeginInvoke which will execute a method asynchronously through a delegate.

iStock_connectTwoWiresXSmall

You can write the EndShowMore call back as follows,

private static void EndShowMore( object state )
{
  Button btn = (Button) state;
  btn.Dispatcher.BeginInvoke(
     delegate() { btn.IsEnabled = false; } );
  btn.Dispatcher.BeginInvoke(
     delegate() { btn.Visibility = Visibility.Collapsed; } );
}

That will certainly work but the syntax is a bit cumbersome. I find the use of a Lambda expression makes the intent clearer and the code a bit simpler,

private static void EndShowMore( object state )
{
   Button btn = (Button) state;
   btn.Dispatcher.BeginInvoke( () => btn.IsEnabled = false );
   btn.Dispatcher.BeginInvoke( 
() => btn.Visibility = Visibility.Collapsed ); }

More On Hyper-Video

For more on the subject of Hypervideo see the thread of blog posts that starts here or these How Do I videos: Part 1, Part 2Part 3. The tutorials (in C# and VB) on Hypervideo should be posted before Mix.


This work is licensed under a Creative Commons Attribution By license.
Share

About Jesse Liberty

Jesse Liberty is an independent consultant and programmer with three decades of experience writing and delivering software projects. He is the author of 2 dozen books and multiple Pluralsight courses, and has been a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Xamarin Certified Mobile Developer and a Xamarin MVP, Microsoft MVP and Telerik MVP.
This entry was posted in z Silverlight Archives. Bookmark the permalink.

Leave a Reply

Your email address will not be published.