0
votes

I'm having issues understanding the Mutex class and how to properly use it in a WP8 application. What I'm attempting to do is allow only a ScheduledAgent or the application to read/write a file to storage at a time. I've tried this various ways with no luck. Any help would be appreciated.

ScheduledAgent code:

Below code errors out when I call ReleaseMutex(). This issue is fixed when I create the Mutex object like so: new Mutex(true, "FlightPathData"). But then I can never get a lock and hangs on WaitOne()

Error

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

Code

readonly Mutex mutex = new Mutex(false, "FlightPathData");

protected async override void OnInvoke(ScheduledTask task)
{
      List<METAR> savedMetars = null;
      var facility = ....;

      bool mutexAcquired = mutex.WaitOne();
      try
      {
           if (mutexAcquired)
           {
               savedMetars = await Data.LoadMetarsAsync(facility.Identifier);
               //Thread.Sleep(15000);
           }
       }
       finally
       {
           if (mutexAcquired)
           {
               mutex.ReleaseMutex();
           }
       }

       NotifyComplete();
 }

ViewModelCode (Works fine till the ScheduledAgent ReleaseMutex() fails)

static readonly Mutex mutex = new Mutex(true, "FlightPathData");
...
mutex.WaitOne();
var savedMetars = await Data.LoadMetarsAsync(this.Facility.Identifier);
mutex.ReleaseMutex();
1
It appears this line: savedMetars = await Data.LoadMetarsAsync(facility.Identifier); Causes the task to enter another thread since it's async and when it tries to release the Mutex it can't. I comment out that code and everything works as it should...very odd.Clarke76
@Stehen: Could you please elaborate a little about "you can't use a mutex with async code"? In my UWP apps I need to synchronize resource access (e.g. to storage files) between the foreground app and its background tasks (living in separate processes). In my tests mutexes seem to work fine (which I know is no prove).Peter Meinl

1 Answers

2
votes

You can't use thread-affine locks with async code. This is because the await can cause the method to return (while holding the mutex) and then another thread can continue the async method and attempt to release a mutex it does not own. If this is confusing, I have an async intro blog post that you may find helpful.

So you can't use Mutex or other thread-affine locks such as lock. However, you can use SemaphoreSlim. In your async methods, you would use await WaitAsync instead of Wait.