EvenTiles from Start to Finish–Part 13

In the previous episode of this series about how to develop a Windows Phone application from scratch we fixed some issues to properly start and renew a PeriodicTask. Now we are ready to find out how an application can communicate with its PeriodicTask.

In today’s EvenTiles episode, you will learn why you cannot simply use a variable to communicate between the application and the PeriodicTask. In my opinion that is important, because understanding why some things are not working makes you a better Windows Phone developer and decreases the chance of having hard to trace bugs inside your own applications. In order to separate the functionality to transfer data between the application and its PeriodicTask, we are going to create a new project inside the EvenTiles solution.

Dump1

The project will be of type Windows Phone Class Library and we will call it EvenTilesComm. In its initial version, this class library will contain one single class with the name TileData. It is used to store the text that the user can enter in the Settings Page of the EvenTiles application in order to allow the PeriodicTask to display this string on the back of the Secondary Tile once it is created. In order to vary the text on the back of the Secondary Tile, TileData will also contain a boolean variable indicating which string needs to be displayed on the Secondary Tile’s backside (either the string passed by the application or a default string that is defined inside the PeriodicTask).

screenTo be able to access TileData from within both the EvenTiles application and the PeriodicTask, it contains two static properties. A string property to store / retrieve the message that is defined through the Settings Page and a boolean property that defines which string needs to be displayed from within the PeriodicTask. The string property is always written by the application and read by the PeriodicTask. The boolean variable is both written by the application and the PeriodicTask but only read by the PeriodicTask. Because of the fact that the PeriodicTask and the application are running inside their own, separate process in different threads, and since they are running completely unsynchronized from each other, there is a possibility that they both want to access one of the properties of TileData at the same time. To prevent this potential dangerous situation (dangerous because it can leave the properties in an undefined state when one of the two different threads want to access them while the other is updating them), both properties are protected by a Mutex synchronization object.

NOTE: The following (initial) implementation of the TileData class will not work properly, but it is shown here to help you understand what it means that an application and its PeriodicTask belong to each other, but are completely separated from each other at the same time. You will have to wait a little while for a working solution, because that will be introduced in the next episode of EvenTiles.

Threadsafe Data Access
  1. public class TileData
  2. {
  3.     private static Mutex mtx = new Mutex(false, "MtxSync");
  4.  
  5.     private static string secondaryBackContent;
  6.     private static bool showDefaultSecondaryBackContent;
  7.  
  8.  
  9.     public static string SecondaryBackContent
  10.     {
  11.         get
  12.         {
  13.             return RetrieveSecondaryBackContent();
  14.         }
  15.         set
  16.         {
  17.             StoreSecondaryBackContent(value);
  18.         }
  19.     }
  20.  
  21.     public static bool ShowDefaultSecondaryBackContent
  22.     {
  23.         get
  24.         {
  25.             return RetrieveShowDefaultSecondaryBackContent();
  26.         }
  27.         set
  28.         {
  29.             StoreShowDefaultSecondaryBackContent(value);
  30.         }
  31.     }
  32.  
  33.     private static string RetrieveSecondaryBackContent()
  34.     {
  35.         mtx.WaitOne();
  36.  
  37.         try
  38.         {
  39.             return secondaryBackContent;
  40.         }
  41.         finally
  42.         {
  43.             mtx.ReleaseMutex();
  44.         }
  45.     }
  46.  
  47.     private static void StoreSecondaryBackContent(string content)
  48.     {
  49.         mtx.WaitOne();
  50.  
  51.         try
  52.         {
  53.             secondaryBackContent = content;
  54.         }
  55.         finally
  56.         {
  57.             mtx.ReleaseMutex();
  58.         }
  59.     }
  60.  
  61.     private static bool RetrieveShowDefaultSecondaryBackContent()
  62.     {
  63.         mtx.WaitOne();
  64.  
  65.         try
  66.         {
  67.             return showDefaultSecondaryBackContent;
  68.         }
  69.         finally
  70.         {
  71.             mtx.ReleaseMutex();
  72.         }
  73.     }
  74.  
  75.     private static void StoreShowDefaultSecondaryBackContent(bool showDefaultContent)
  76.     {
  77.         mtx.WaitOne();
  78.  
  79.         try
  80.         {
  81.             showDefaultSecondaryBackContent = showDefaultContent;
  82.         }
  83.         finally
  84.         {
  85.             mtx.ReleaseMutex();
  86.         }
  87.     }
  88. }

If you look at the source code of the TileData class, you can see that we are using a two properties through which we are calling a few private methods to actually store or retrieve data. You will also see that we define a single Mutex inside the TileData class. This Mutex has a name, meaning it can be used to synchronize threads over multiple processes. This is important, since EvenTiles and its PeriodicTask will execute in separate processes. If we take a look at one of the individual retrieval methods, you will see how the single Mutex that is defined in TileData is used.

Retrieving data
  1. private static string RetrieveSecondaryBackContent()
  2. {
  3.     mtx.WaitOne();
  4.  
  5.     try
  6.     {
  7.         return secondaryBackContent;
  8.     }
  9.     finally
  10.     {
  11.         mtx.ReleaseMutex();
  12.     }
  13. }

In this method, we access the variable secondaryBackContent only when the method WaitOne on our Mutex returns. When WaitOne returns, our method has exclusive access to the variable secondaryBackContent until we call the method ReleaseMutex on our Mutex. At that moment, another thread that is waiting for the same Mutex will be granted access. Every method that uses of a Mutex to get access to protected data must under all circumstances call ReleaseMutex when it is done. That is the reason why we are adding a try / finally block. The code in the finally block will execute, even when exceptions are thrown. In this way, we prevent our application from a potential deadlock situations (where multiple threads are waiting on each other to free up a synchronization object that is never being freed).

The way data is protected for EvenTiles works properly, which can be verified by debugging the application and deliberately skipping a call to ReleaseMutex from within the EvenTiles application (which is fully explained in the accompanying video as well). Doing so will result in the PeriodicTask waiting forever for the Mutex, because it will never be released by the application. This at least proves that both EvenTiles and its PeriodicTask are making use of the same Mutex that they both need to own before being able to access variables.

There is still a potential problem, because we are calling the WaitOne method without parameters, which means that we will wait indefinitely until the Mutex becomes available. In our simple example this is sufficient, but in a real application you most likely want to wait for a specific time and take action upon timeouts.

However, there is a way bigger problem with the current implementation of our newly created TileData class. We already saw that the Mutex is properly shared between EvenTiles and its PeriodicTask, but what about the public properties. The following screen dump shows you what is wrong with the TileData class right now. Even though the variable secondaryBackContent is set by the EvenTiles application, it seems that it is not initialized when the PeriodicTask retrieves the variable (both through the appropriate properties).

image image

Since our EvenTiles application and its PeriodicTask are running in separate processes, they are completely separated from each other, meaning that they get their own copies of variables they both want to access, even though these variables are defined in a separate project. This is a good thing (even though we have to solve the problem), because otherwise all variables used by every process on the phone would need a unique name. The following video shows EvenTiles in action in combination with its PeriodicTask. It shows how the Mutex works and how passing data fails.

Protecting variables against simultaneous access by multiple threads

To be able to experiment with this wrong implementation of EvenTiles, especially to understand how the application interacts with the PeriodicTask, the sample code is available for dowload here.

Instead of using ‘simple’ variables to pass data between EvenTiles and its PeriodicTask, we will have to make use of IsolatedStorage and have them share data through a file. That will be the topic of the next episode of EvenTiles.