Using the Async CTP With Windows Phone

January 7, 2012

no comments

The Async CTP that exposes C# 5.0 features to be used with asynchronous programming is not just for the full .NET Framework. There are versions for Silverlight (4 and 5) and even Windows Phone (which can be viewed as Silverlight 4, but has a separate supporting assembly).

To demonstrate, I’ve adapted my sample of the Mandelbrot set to Windows Phone, while taking advantage of the async features to keep the UI responsive.

After creating the initial Silverlight for Windows Phone project, I’ve added a reference to the async CTP library, which can be found under {MyDocuments}\Microsoft Visual Studio Async CTP\Samples:

image

You can see the other versions for Silverlight (4 with no suffix, and 5) and of course, the desktop one (without any suffix).

The calculation and rendering loop looks like this:

async void RunMandelbrotAsync(Complex from, Complex to, CancellationToken ct) {
	int width = _bmp.PixelWidth, height = _bmp.PixelHeight;
	double deltax = (to.Real - from.Real) / _bmp.PixelWidth;
	double deltay = (to.Imaginary - from.Imaginary) / _bmp.PixelHeight;
	try {
		int[] pixels = new int[width];
		for(int y = 0; y < height; y++) {
			if(ct.IsCancellationRequested)
				break;
			await TaskEx.Run(() => {
				for(int x = 0; x < width; x++) {
					pixels[x] = MandelbrotColor(from + new Complex(x * deltax, y * deltay));
				}
			}, ct);
			if(!ct.IsCancellationRequested) {
				Array.Copy(pixels, 0, _bmp.Pixels, y * width, pixels.Length);
				_bmp.Invalidate();
			}
		}
	}
	catch(TaskCanceledException) {
	}
}

The code is somewhat different than the original version. First, the Parallel class does not exist (yet…) in the Windows Phone API, so I replaced it with a regular for loop. The asynchrony is achieved by running the inner loop using a separate Task and “awaiting” it. Another twist added in this version is the ability to cancel the operation.

The TaskEx.Run is a kind of shorthand to creating a Task, calling Start and returning that Task (in the final version it would be part of the Task class).

Other differences in the code result from more API differences between Silverlight and WPF, such as the WriteableBitmap class. No pixel format can be specified in Silverlight (including WP7), and is always ARGB, so I had to change the MandelbrotColor method to return a matching pixel format:

int MandelbrotColor(Complex c) {
int
color = 255;
Complex z = Complex
.Zero;
while
(color > 0 && z.Real + z.Imaginary < 4) {
z = z * z + c; color–; }
return (int)((255 << 24) | (color << 16) | (color << 8) | color);
}

Note also the Complex type. This does not (yet…) exist in Silverlight! I’ve actually duplicated the code in the .NET 4 Complex type by dumping it as source using Reflector, and then removing the unsupported stuff (Serializable and and some other unsupported attributes, as well as a conversion from a BigInteger). This is possible because a Complex is basically a mathematical entity, and does not use the framework in any special way.

You can run the application on the emulator or a real device. Doing a double-tap (double click in the emulator) causes the resolution to increase (building slower). To get a double tap, I’ve used the new DoubleTap event introduced in Windows Phone 7.1 (“Mango”).

This is how it looks initially (the emulator is rotated):

image

Tapping and dragging a rectangle allows zooming in on a specific area. The resolution is reset, so more double taps are required to increase the resolution again. Here’s how it looks after double-tapping twice:

image

This is while selecting a zoom rectangle:

image

And the result (after 2 more double taps):

image

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*