This referes to Building Async Coordination Primitives, Part 6: AsyncLock , http://winrtstoragehelper.codeplex.com/ , Windows 8 app store and .net 4.5
Here is my angle on this:
The async/await language feature makes many things fairly easy but it also introduces a scenario that was
rarely encounter before it was so easy to use async calls: reentrance.
This is especially true for event handlers, because for many events you don't have any clue about whats happening after you return from the event handler.
One thing that might actually happen is, that the async method you are awaiting in the first event handler, gets called from another event handler still on the
same thread.
Here is a real scenario I came across in a windows 8 App store app:
My app has two frames: coming into and leaving from a frame I want to load/safe some data to file/storage.
OnNavigatedTo/From events are used for the saving and loading. The saving and loading is done by some async utility function (like http://winrtstoragehelper.codeplex.com/).
When navigating from frame 1 to frame 2 or in the other direction, the async load and safe operations are called and awaited.
The event handlers become async returning void => they cant be awaited.
However, the first file open operation (lets says: inside a save function) of the utility is async too
and so the first await returns control to the framework, which sometime later calls the other utility (load) via the second event handler.
The load now tries to open the same file and if
the file is open by now for the save operation, fails with an ACCESSDENIED exception.
A minimum solution for me is to secure the file access via a using and an AsyncLock.
private static readonly AsyncLock m_lock = new AsyncLock();
...
using (await m_lock.LockAsync())
{
file = await folder.GetFileAsync(fileName);
IRandomAccessStream readStream = await file.OpenAsync(FileAccessMode.Read);
using (Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result)
{
return (T)serializer.Deserialize(inStream);
}
}
Please note that his lock basically locks down all file operation for the utility with just one lock, which is unnecessarily strong but works fine for my scenario.
Here is my test project: a windows 8 app store app with some test calls for the original version from http://winrtstoragehelper.codeplex.com/ and my modified version that uses the AsyncLock from Stephen Toub.
May I also suggest this link:
http://www.hanselman.com/blog/ComparingTwoTechniquesInNETAsynchronousCoordinationPrimitives.aspx