Deceptive simplicity of async and await

January 23, 2012 in .NET, async, C#, WinRT

By introducing the new async/await keywords in C# 5 and by adding asynchronous APIs in .NET 4.5, Microsoft significantly lowered the bar for entering into the realm of the asynchronous programming. However, while presenting the new features of the upcoming .NET Framework release, answering the questions and helping to resolve the first issues I came to realization that this bar might be set too low.

These new additions help us to create asynchronously running methods using the familiar synchronous development model. We don’t need to segment our code to extract the parts to be executed in a separate thread or to be a callback. We don’t have to think about the threads or tasks anymore – just add await and the rest is done automatically.

That’s cool – I really like these new features and I believe they can simplify our lives, but only when used properly. Current development stack (Win7/.NET Framework 4) does not enforce the asynchronous development model. The async functionality can be introduced into existing synchronous application once the developer has fully realized the advantages of the async APIs and has mastered their proper usage.

WinRT and .NET 4.5 are different – this stack forces us to use async model. Again, this is not a bad thing but it requires some discipline and some preliminary knowledge. Right now many developers are new to the field and are experiencing the following:

Developer: “I want to use this function to read some data”
Compiler: “Good, but you may want to use await to get the string”
Developer: “OK, await is added. Can I get the string?”
Compiler: “Sure, just add async in the method header”
Developer: “Added. F5!”
Developer: “Hey, it does not work! Where is my string?”

The code looks good, it can be compiled but does not work. Why? Here are two most common mistakes I have seen so far.

Example 1

WriteFileAsync function definition:

async public void WriteFileAsync(string filename, string contents)
{
    var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    var file = await localFolder.CreateFileAsync(filename, 
                           Windows.Storage.CreationCollisionOption.ReplaceExisting);
    var fs = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);     
    //...
}

And this function is called as

WriteFileAsync("FileName", "Some Text");

In some cases this code will work properly. But only in some – if there is a code that depends on the file content or tries to access the same file and this code is called after WriteFileAsync(), the developer will be faced with an exception or unpredicted results.

The problem here is that the developer use awaits for the system calls but WriteFileAsync by itself is not awaitable and any code following after WriteFileAsync() call will be executed before all the expected saving operations are done. To fix the issue the method should be modified

async public Task WriteFileAsync(string filename, string contents)
{
    //...
}

And the function should be called as

await WriteFileAsync("FileName", "Some Text");

Example 2

To implement Windows 8 Sharing contract, an application should handle DataTransferManager.DataRequested event. Below you can see an example of such a handler:

async void DataRequestedHandler(DataTransferManager sender, DataRequestedEventArgs args)
{
    _fileStream = await _lastSelectedFile.OpenAsync(FileAccessMode.Read);
 
    args.Request.Data.Properties.Title = "Data Title";
    args.Request.Data.SetBitmap(_fileStream);
}

Not surprisingly, this sample does not work either. DataTransferManager does not expect that handler is asynchronous and when the await keyword returns control to the manager, the latter sees an empty data request object, assumes that the contract is not properly implemented and will not show the application on the Share panel. The fix is easy, we just need to move OpenAsync out of the method and to remove async keyword from the header, but this example demonstrates another kind of side effects – we should be very careful with the async functions when some data are expected to be returned to the external code.

These mistakes look trivial but chances are they will appear quite often due to deceptive simplicity of the new syntax. Hopefully, the next version of Visual Studio and/or ReSharper will be able to detect such situations and warn about them.

What is your opinion? Do you see a problem here?

My Metro Toronto UG presentation slides and samples

January 18, 2012 in .NET, C#, Talk, Windows 8, WinRT

The slides and sample code from my “Windows 8 Development – Deeper Dive” presentation for Metro Toronto User Group are available for download.

The samples archive contains two demo projects:
  1. MetroDemo demonstrates file system APIs and implementation of Share, File Picker and Search contracts.
  2. TilesDemo demonstrates the basic manipulations with the application tiles.

Some comments about the MetroDemo project:
  • In addition to the contracts demonstrated during the demo, the attached code demonstrates an implementation of the Search contract.
  • To see the demo in action your Pictures Library must contain at least one image tagged with some keywords. The keyword can be added in Windows Explorer by selecting the images and entering this data on the Details pane.
  • What is ObservableVector.cs: ObservableCollection class is supported by Windows 8 Developer Preview but the change notification events are ignored by WinRT UI controls. ObservableVector class is a workaround to resolve the issue – it wraps an ObservableCollection object and allows us to send the notifications to the UI.
 

Is there a future for Microsoft Expression Blend for XAML?

December 15, 2011 in Blend, XAML

I am not a fan of the visual designers and prefer to create UI by writing XAML code instead of dragging and dropping the controls. But from time to time I launch Expression Blend to create some animations, gradients or complex styles and I have to admit that Blend is a wonderful tool. Many developers like it. From the other side, Blend was created in the first place for the designers, not for the developers and from this point of view Blend is a failure. I have seen several attempts to teach UX experts to use Blend for sketching and designing and most of them failed. For the designers the learning curve is too steep, many features require some software development knowledge to use them properly.

During the BUILD conference Microsoft presented Expression Blend 5 Developer Preview that supports HTML only. Visual Studio 11 includes an improved XAML designer and some panels and controls that will look familiar for the Blend users but there is no any information on a standalone Blend for XAML. Taking into account that the whole BUILD event was designed to attract JavaScript/HTML developers and the preview status of the tools, I stayed calm waiting for the news. Until now.

Microsoft Advertising SDK for Windows 8 documentation includes an interesting table comparing the functionality available right now in a Preview Release with the features of a “Formal Launch”.

One row catches my eye:

Is it an answer for the question about the future of Blend for XAML or just an inaccuracy of the documentation?

On deploying ASP.NET MVC site as a desktop application

December 9, 2011 in .NET, ASP.NET, C#, Fileversum, Web

Sometimes you may find you in a situation when you have an ASP.NET web application and want to deploy it to a desktop PC. For example, for one of my projects I have the following requirements:

  • Simple installation on any Windows-based PC. Installation and configuration should not require knowledge of the Web technologies.
  • Ability to start, stop and configure the Web application from a custom desktop application.
  • The Web application should be accessible for a local user and all the network users.
  • In the same time it should be a regular ASP.NET application that can be deployed as a hosted solution.

It is clear that such solution will be composed from 3 main components: Web application, control application (in my case it is based on .NET/WPF), Web server. And the main question is “What should I use as a server?” To satisfy the project’s requirements, the server should have the following characteristics:

  • Easily redistributable
  • Configurable via API, configuration files or command line
  • Should be controllable externally (Start/Stop via API, command line, etc.)
  • Network support

 

CassiniDev

Already having an experience with CassiniDev server as a solution for the integration tests execution, I tried this one first. CassiniDev is an open-source project that includes a standalone Wev server with GUI and a library. The library, CassiniDev4-Lib.dll, contains CassiniDevServer class – an in-process Web server implementation.

_server = new CassiniDevServer();
_server.StartServer(@“\path\to\web\content”));

Basically, that’s it – with two lines of code you have a server that hosts your ASP.NET application. At first look this is what is required:

  • there is no need to install anything – the server is a part of the control application
  • CassiniDevServer can be easily configured and controlled

But there are some cavities and probably the main one is performance. CassiniDev handles all the HTTP requests sequentially, in one thread. It is acceptable for testing but is not practical in production.

Another issue that kicks CassiniDev out of completion is an auto-shutdown after 60-seconds of idleness – it simply stops to handle any incoming requests.

IIS Express

IIS Express is a lightweight version of IIS. It runs as a separate process like full version of IIS web server, but this process is executed under the user’s account. IIS Express is a standalone application and can be started/stopped using a command line, unlike service-based full IIS.

Theoretically IIS Express is xcopy-deployable, but EULA states that IIS Express can only be redistributed using an official installer package. That means if you want to use IIS Express, it should be added as a prerequisite to your installer and will be installed as separated product.

IIS Express uses the same configuration mechanism as full IIS. Probably the easiest way to host the site on IIE Express, is to create own applicationhost.config, deploy it on the target system and use it to start the server:

“C:\Program Files\IIS Express\iisexpress.exe” /config:D:\Fileversum\config\applicationhost.config

Even IIS Express is installed into the system it will not be started automatically on the Windows start. You have to do it by yourself by creating some kind of launcher or incorporating this functionality into the control application, to be able to start/stop the server on-demand.

By default IIS Express does not require elevated permissions, but in the same time it default configuration does not support network requests and port 80. You need the administrative privileges to unlock these features. The post by Scott Hanselman describes the required manipulations, but in short you need to do the following:

  • Configure applicationhost.config to bind your site with the public IP address.
  • Allow incoming connections and add a new Windows Firewall rule using netsh utility.

Note that netsh does not exist in Windows XP and httpcfg should be used instead. That means an additional complexity for the installation script.

UltiDev Web Server Pro

UltiDev Web Server Pro is a successor for UltiDev Cassini Web Server, a freeware redistributable Web server. The product is relatively new, but it is in active development and demonstrates a good stability, performance and a reach feature set.

Like IIS Express, UWS is a standalone out-of-process Web server. It runs as a service, includes GUI frontend but also provides an API and the command line tools. UltiDev Server cannot be privately deployed, you have to install it. Fortunately the server redistributable packages for InstallShield, Advanced Installer and VS bootstrapper are available.

If you prefer to register your site during the installation, UWS provides a command line utility that can be used for this propose. If you need more control under the site’s lifecycle, a .NET-based API exposed from UWS.Configuration.dll library might be an option. Below you can see a sample code demonstrating site registration:

var app = Metabase.GetWebAppEntry(ApplicationGUID, false);
app.VirtualDirectory = "/Fileversum";
app.PhysicalDirectory = @“\path\to\web\content”;
app.ApplicationName = "Fileversum";
app.AppType = ApplicationType.AspNetOrStaticHtml;
app.ListenAddresses.AddRange(new[] { new ListenAddress(80) });
 
Metabase.RegisterApplication(RuntimeVersion.AspNet_4, true, app);

And un-registration:

Metabase.UnregisterApplication(ApplicationGUID);

Both operations (registration and un-registration) require the administrative rights. So if this code is incorporated into the control application, it must be able to request the elevated partitions.

As soon as the site is registered, it will be available for the local and the network users. No additional actions are required to start the server or site after Windows reboot.

Additionally, to simplify the site deployment, UWS supports auto detection of the available ports.

My CTTDNUG presentation slides and samples

December 1, 2011 in .NET, C#, Talk, Windows 8, WinRT

I published the slides and sample code from my presentation about Windows 8 at Canada’s Technology Triangle .NET User Group meeting. The slides are also available on Slideshare.

Feel free to contact me if you want to discuss them.

Exploring WinRT: Storage.AccessCache

October 10, 2011 in C#, File System, Windows 8, WinRT

Exploring WinRT:

1. Windows.Storage namespace overview
2. File and Folder Pickers
3. Storage.AccessCache

Let’s imagine that we are creating a Metro style text editor. With help of the pickers users are able to open and save files at any location. But what if the user wants to reopen a file he or she edited last week? Do we need to show the picker and ask him to open file again? It will be nice to have a list of the recently used documents and provide a way to reopen them with one click.

Fortunately, WinRT architects thought about this scenario and introduced several classes grouped together within Windows.Storage.AccessCache namespace:

...
StorageFile file = await filePicker.PickSingleFileAsync();
string token = StorageApplicationPermissions.FutureAccessList.Add(file, “metadata”);

If you have an object of StorageFile or StorageFolder type and you want to keep it accessible, class StorageItemAccessList provides you a way. Method Add() will add your file system object to the list and return a string token (GUID) that can be used in the future to get the object back. All the added objects stay accessible even after application restart and can be easily retrieved without interacting with the user:

if (StorageApplicationPermissions.FutureAccessList.ContainsItem(folderID))
{
   StorageFolder folder = 
         await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(folderID);
   ...
}

where StorageApplicationPermissions is a static class declared in Windows.Storage.AccessCache.

If you want to provide your own token, there is an alternative to Add() method:

StorageApplicationPermissions.FutureAccessList.AddOrReplace(“LastUsedFile”, file, “metadata”);

This method adds a new item to the access list, or replaces the specified item if it already exists in the list. The last parameter for both Add() and AddOrReplece() is an optional metadata to associate and store with the file system object. There is no special methods to access the metadata, it is only accessible through Entries collection:

...
AccessListEntry item = StorageApplicationPermissions.MostRecentlyUsedList.Entries[n];
string metadata = item.Metadata;
...

The same tokens are used to remove the items from the access list, using Remove(). Or you can use Clear() method to wipe out the list completely. These methods are important because the list is not boundless – the maximum number of the items in the list is indicated by MaximumItemsAllowed and for me it is equal to 25. Yes, just 25 items can be saved simultaneously, so goodbye an idea to track all the files ever used.

It is very common situation, when your app is trying to open a previously used file but the file does not exist because it is already renamed or moved. Good news: FutureAccessList tracks this situation automatically. Even if the file or folder moved, it is still associated with the same token and will be returned to you when you need it.

In addition to FutureAccessList, StorageApplicationPermissions includes MostRecentlyUsedList property of StorageItemMostRecentlyUsedList class. This is an independent list that implements the same functionality as FutureAccessList and can keeps up to 25 storage items. The only difference is an ItemRemoved event, implemented by StorageItemMostRecentlyUsedList, but I was not able to trigger it – Remove() and Clear() do not fire this event. It is not clear why do we need both classes and my best guess that MRU list will be used by system somehow, but in the Developer Preview version these interactions are not implemented yet.

Exploring WinRT: File and Folder Pickers

October 7, 2011 in C#, File System, Windows 8, WinRT

Exploring WinRT:

1. Windows.Storage namespace overview
2. File and Folder Pickers
3. Storage.AccessCache

So, because we are very restricted in accessing file system directly, sometimes we will need user’s help to access files and folder. There are three classes that give app access to the locations unavailable through Storage APIs – FileOpenPicker, FileSavePicker and FolderPicker - Windows 8’s replacement for the well know Open/Save dialogs. They represent UI elements that let users choose files and folders to open or file name and location to save a file.

FileOpenPicker

Using the picker, user can browse the file system and select one or multiple files to open. The following code was used to show this screen:

var filePicker = new FileOpenPicker();
filePicker.FileTypeFilter.Add(".jpg");
filePicker.ViewMode = PickerViewMode.Thumbnail;
filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
filePicker.SettingsIdentifier = "picker1";
filePicker.CommitButtonText = "Open File to Process";
 
var files = await filePicker.PickMultipleFilesAsync();

To use the file picker, you have to add at least one file extension to FileTypeFilter collection, to indicate what file types are supported by the app. If FileTypeFilter is empty, file picker will throw “Unspecified error” exception on open.

There is no way to say “show all files” – filter “.*” does not supported. Also, there is no way to open files without extension. FileTypeFilter accepts “.” as the filter but does not show anything when this filter is used.

All other properties are optional.

ViewMode property allows you to define how the items will be displayed. You can choose between Thumbnail and List, but be careful selecting the appropriate mode. User will not be able to switch it within the picker and may not be very happy if you will propose him to select an image using List view.

SuggestedStartLocation is used to suggest to the picker a folder to display. “Suggest” is a right word – this property is used only once, when the picker is opened for the first time. Next time when picker will be used, even if the application was restarted, the property is ignored and the last used folder is used as the start location.

Moreover, if you have more than one file picker in your app, all of them will share the same start location. If this behaviour is not what you expected, you can use SettingsIdentifier property to define to define a scope – all the pickers with the same SettingsIdentifier will share the same start location. The opposite is also true – locations for the pickers with the different identifiers are tracked separately.

CommitButtonText can be used to override standard “Open” text with something more specific.

And, finally, one of the two functions – PickMultipleFilesAsync or PickSingleFileAsync – should be used to show the configured picker to the user.

FileSavePicker

var fileSavePicker = new FileSavePicker();
fileSavePicker.FileTypeChoices.Add("Raw Images", new List<string> { ".raw", ".dat" });
fileSavePicker.FileTypeChoices.Add(".jpg Image", new List<string> { ".jpg" });
fileSavePicker.DefaultFileExtension =.jpg;
fileSavePicker.SuggestedFileName = “i08.jpg;
filePicker.SettingsIdentifier = "picker1";
 
var fileToSave = await fileSavePicker.PickSaveFileAsync();

Similar to FileOpenPicker you have to add at least one file type to FileTypeChoices collection and the rest of the properties are optional.

If your app supports multiple file types, you can use DefaultFileExtension property to define a preferred one. Also the app can set SuggestedFileName property to suggest a full file name, so users don’t need to type it. Alternatively, if StorageFile object is already instantiated, you can use SuggestedSaveFile property

fileSavePicker.SuggestedSaveFile = file;

and it will automatically extract the default extension and suggested file name for you.

FileSavePicker.SettingsIdentifier works identical to FileOpenPicker.SettingsIdentifier and you can use the same identifiers to synchronize the open and save pickers.

ViewMode is not supported by FileSavePicker.

Method PickSaveFileAsync() returns StorageFile object linked with a newly created zero-sized file. If user selected existed file and allowed to override it, the file will be deleted and replaced with an empty one with the same name.

FolderPicker

There is nothing special about this dialog; the properties and usage are pretty similar to FileOpenPicker.

var folderPicker = new FolderPicker();
folderPicker.FileTypeFilter.Add(".jpg");
folderPicker.ViewMode = PickerViewMode.Thumbnail;
folderPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
folderPicker.SettingsIdentifier = "FolderPicker";
 
var folder = await filePicker.PickSingleFolderAsync();

Exploring WinRT: Windows.Storage namespace overview

October 3, 2011 in C#, File System, Windows 8, WinRT

Exploring WinRT:

1. Windows.Storage namespace overview
2. File and Folder Pickers
3. Storage.AccessCache

Presenting Windows 8, Microsoft put a lot of emphasis on the new UI design and the users experience improvements. But for me, as the productivity and file management tools developer, UI-related changes, changes in the installation process, OS integration and file system access are equally important. In this post and the following posts I’d like to share my findings and thoughts related to these APIs.

As we already know, file system access for the WinRT apps is heavily restricted. The following diagram represents the big picture and was widely discussed during the BUILD sessions.

The full, unrestricted access is enabled for the app’s local folder only, located in C:\Users\<user_name>\AppData\Local\Packages\<package>. Within the local folder you can create, modify and delete files and folders without asking user’s permission. Local data access is provided using Windows.Storage.ApplicationData class:

var localFolder = ApplicationData.Current.LocalFolder;
var file = await localFolder.CreateFileAsync("data.txt");

If you are planning to access user’s documents, music, videos or any other data located in one of the system libraries, you have to indicate it through the app’s manifest. If app is trying to access a library item without specifying the corresponding capability in manifest, a runtime exception System.UnauthorizedAccessException will be thrown notifying you that access is denied.

Manifest editing is simple with new manifest designer integrated into Visual Studio 11:

Manifest editor

For the Music, Picture and Video libraries you are specifying the features you want in the Capabilities list and you are done. For the Documents Library things are more complicated. In addition to specifying Documents Library Access, you have to specify all the file types you want to be able to access using File Type Association declaration:

File Type Association

The reasons for this implementation are understandable, but it does not mean that I like it. I can imagine multiple scenarios when tools may need an access to the files with an unknown type. Yes, apps can use File Picker to access these files, but it requires interaction with user and in the certain cases prevents tasks automation.

Anyway, when manifest is configured properly, the library files and folders become available to the app with help of Windows.Storage.KnownFolders class:

var pictures = KnownFolders.PicturesLibrary;
var allPictures = pictures.GetFilesAsync();

Do you need a programmatic access to the files outside of the local folder or the libraries? Sorry, there is no API for this. File picker is your best friend here – let your user to choose files for you. There is only one exception – user’s Downloads folder.

To access Downloads folder your app does not need to specify any capabilities in the manifest, but in return it has write-only access to the folder. Windows.Storage.DownloadsFolder class is declared as static and exposes two methods only – CreateFolderAsync and CreateFileAsync. Of course, once your app created a new file (folder) and retrieved StorageFile (StorageFolder) object, it has full access to this item. But as soon as the object is disposed, the newly created files and folders become unavailable for you.

var folder = DownloadsFolder.CreateFolderAsync("New Folder");
// working with the folder ...

And last thing to overview is the application’s installation folder. This folder is located in C:\Users\<user_name>\AppxLayouts\ and, surprisingly, is read/write accessible via Windows.ApplicationModel.Package class:

var installationFolder = Package.Current.InstalledLocation;
var newFolder = await installationFolder.CreateFolderAsync("Setup");