Windows Phone 7–Threading Issues With the Stopwatch Class

I am writing a profiling application to help me with some performance problems that I am having with the Windows Phone 7 game I am writing.  Here is a snippet where I track the time it takes to load in the game data for a given scenario:

1 private void LoadTile() 2 { 3 Stopwatch stopWatch = new Stopwatch(); 4 ScenarioTileFactory scenarioTileFactory = new ScenarioTileFactory(); 5 List<ScenarioTile> scenarioTiles = null; 6 stopWatch.Start(); 7 scenarioTiles = scenarioTileFactory.GetScenarioTiles(20); 8 stopWatch.Stop(); 9 this.TilesListBox.Items.Add(String.Format("Scenario {0} has {1} tiles and it took {2}.", 10 "20", scenarioTiles.Count.ToString(), stopWatch.ElapsedMilliseconds.ToString())); 11 12 } 13

When I run it, I get this (which is correct):

image

I then wanted time how long each scenario takes to load and update the UI after each load.  I immediately thought of using a second thread – 1 to load the data and the main UI thread to update the screen.  I update my load function for multi-threading like so:

1 Stopwatch stopWatch = new Stopwatch(); 2 ScenarioTileFactory scenarioTileFactory = new ScenarioTileFactory(); 3 List<ScenarioTile> scenarioTiles = null; 4 stopWatch.Start(); 5 scenarioTiles = scenarioTileFactory.GetScenarioTiles(20); 6 stopWatch.Stop(); 7 this.TilesListBox.Dispatcher.BeginInvoke(() => 8 { 9 this.TilesListBox.Items.Add(String.Format("Scenario {0} has {1} tiles and it took {2}.", 10 "20", scenarioTiles.Count.ToString(), stopWatch.ElapsedMilliseconds.ToString())); 11 }); 12 stopWatch.Reset(); 13 stopWatch.Start(); 14 scenarioTiles = scenarioTileFactory.GetScenarioTiles(21); 15 stopWatch.Stop(); 16 this.TilesListBox.Dispatcher.BeginInvoke(() => 17 { 18 this.TilesListBox.Items.Add(String.Format("Scenario {0} has {1} tiles and it took {2}.", 19 "21", scenarioTiles.Count.ToString(), stopWatch.ElapsedMilliseconds.ToString())); 20 }); 21

The results started getting screwy:

image

 

It sure looks like the Stopwatch.Reset is not thread-aware? Nope, hoping the thread back calls an auto refresh. For example, I put a break:

image

 

But when I hop the thread and go back to the UI thread:

image

So the stopwatch class is not thread-safe. Good to know! To get around this problem, I created a local holding variable and passed that value over to the UI thread:

1 private void LoadTiles() 2 { 3 Stopwatch stopWatch = new Stopwatch(); 4 ScenarioTileFactory scenarioTileFactory = new ScenarioTileFactory(); 5 List<ScenarioTile> scenarioTiles = null; 6 long elapsedTime = 0; 7 for (int i = 0; i < 30; i++) 8 { 9 stopWatch.Reset(); 10 stopWatch.Start(); 11 scenarioTiles = scenarioTileFactory.GetScenarioTiles(i); 12 stopWatch.Stop(); 13 elapsedTime = stopWatch.ElapsedMilliseconds; 14 15 this.TilesListBox.Dispatcher.BeginInvoke(() => 16 { 17 this.TilesListBox.Items.Add(String.Format("Scenario {0} has {1} tiles and it took {2}.", 18 i.ToString(), scenarioTiles.Count.ToString(), elapsedTime.ToString())); 19 }); 20 } 21 } 22

 

Now I have accurate diagnostic information for my analysis:

 

image

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: