August 2012 3 posts

Synchronization in async C# methods

Wednesday, August 29, 2012


The C# keyword async allows one to write synchronous-looking asynchronous code. While very convenient, sometimes there are non-obvious pitfalls.

Suppose in an async method, we want to await something while holding a lock. An example might be a critical section where two network requests should never be made concurrently. The following results in a compile-time error because you cannot use await inside a lock block:

lock (foo) {
    await Task.Delay(1);
}

(Task.Delay(n) is a Task that does nothing and completes after n milliseconds. I'm using it here as a convenient example of an asynchronous operation.)

You may think to use System.Threading.Mutex:

private Mutex mutex = new Mutex();
public async Task DoSomethingAsync() {
    mutex.WaitOne();
    await Task.Delay(1);
    mutex.ReleaseMutex();
}

The catch here is that many, but not all, awaited methods will resume execution on a different thread than the calling thread. In the example above, Task.Delay(n) resumes on a different thread whenever n > 0, so the thread that attempts to release the Mutex will be different than the one which acquired it. Because a Mutex must only be released by the same thread that acquired it, the following exception will be thrown:

System.ApplicationException: Object synchronization method was called from an unsynchronized block of code.

However, you can just use System.Threading.Semaphore to do the same thing, since these aren't bound to any particular thread:

private Semaphore semaphore = new Semaphore(1, 1);
public async Task DoSomethingAsync() {
    semaphore.WaitOne();
    await Task.Delay(1);
    semaphore.Release();
}

Of course, if you are holding synchronization objects for long periods of time as implied by the await keyword, it may be worth rethinking the design to avoid this issue and the inevitable blocking of threads during long asynchronous operations.

Tags: csharp, synchronization, mutex, async | Posted at 10:38 | Comments (7)

Parsing URI query strings in Windows 8 metro-style apps

Tuesday, August 21, 2012


Take the URL string http://example.com/?a=foo&b=bar&c=baz. How do we parse its query parameters using C# to get a dictionary or other key-value data structure?

In .NET, you can use HttpUtility.ParseQueryString(), but that function isn't present in WinRT APIs. Fortunately, there is a replacement: WwwFormUrlDecoder. The code below demonstrates its capabilities:

using System;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Windows.Foundation;

[TestClass]
public class Tests
{
    [TestMethod]
    public void TestWwwFormUrlDecoder()
    {
        Uri uri = new Uri("http://example.com/?a=foo&b=bar&c=baz");
        WwwFormUrlDecoder decoder = new WwwFormUrlDecoder(uri.Query);

        // named parameters
        Assert.AreEqual("foo", decoder.GetFirstValueByName("a"));

        // named parameter that doesn't exist
        Assert.ThrowsException<ArgumentException>(() => {
            decoder.GetFirstValueByName("not_present");
        });

        // number of parameters
        Assert.AreEqual(3, decoder.Count);

        // ordered parameters
        Assert.AreEqual("b", decoder[1].Name);
        Assert.AreEqual("bar", decoder[1].Value);

        // ordered parameter that doesn't exist
        Assert.ThrowsException<ArgumentException>(() => {
            IWwwFormUrlDecoderEntry notPresent = decoder[3];
        });
    }
}

Tags: metro, winrt, csharp | Posted at 15:36 | Comments (1)

Writing a Windows 8 Metro Hello World app using C#, XAML, and calling into a C++ component

Sunday, August 5, 2012


Windows 8 and the new WinRT promises fluid interoperability between C#, C++, and HTML/Javascript. Today we'll take a quick look at a Hello World app built using C# and XAML calling into a C++ component.

First, create a new blank C#/XAML app and call it HelloInterop:

Visual Studio 2012 New Project dialog

Next, add a new project to this solution:

Adding new project to existing solution

Choose the C++ Windows Runtime Component project type and call it HelloCpp.

New Project dialog with C++ selected

Finally, right click on the C# HelloInterop project in the Solution Explorer and choose "Add Reference..." then add the C++ component as a reference (you may have to choose "Solution" on the left pane first):

Adding project reference to project in same solution

Now, we'll work on the C++ code. Open up Class1.h. (Feel free to rename it, but for this guide we'll just stick with this name.) Notice that it's a public ref class and is contained within a namespace — this is required if this class is to be visible to external consumers. Let's add a simple function. Add this line under the constructor's declaration:

Platform::String^ ConcatString(Platform::String^ a, Platform::String^ b);

Now open Class1.cpp and implement this function by adding this code to the bottom of the file:

String^ Class1::ConcatString(String^ a, String^ b)
{
    return String::Concat(a, b);
}

To make the app call this function, let's add a TextBlock to the main page. Open MainPage.xaml and add this line to the page inside the Grid:

<TextBlock Name="CppTextBlock"/>

In MainPage.xaml.cs, add some code inside OnNavigatedTo() to set the text of this element:

var c = new HelloCpp.Class1();
this.CppTextBlock.Text = c.ConcatString("Hello ", "World");

Now run the app and you should see "Hello World" on your screen.

Tags: metro, winrt, csharp, cplusplus, xaml | Posted at 19:50 | Comments (0)