Search code examples
windows-runtimelocking.net-4.5winrt-async

Metro App FileIO.WriteTextAsync Multiple Threads


I have a method which is called frequently from multiple threads. It involves writing to disk using await FileIO.WriteTextAsync. This works fine when it is called from a single thread, but once I start doing this in multiple threads, I get this error:

The process cannot access the file because it is being used by another process.

I know what the error means, but I'm not sure how to work around it. Normally, I would create a lock(object) statement, to ensure that the file is being accessed by only one thread at a time. However, this is an asynchronous method and as such I can't use the await operator in the body of the lock(object) statement.

Please advise on how to handle this scenario.


Solution

  • You can use SemaphoreSlim to act as an async-compatible lock:

    SemaphoreSlim _mutex = new SemaphoreSlim(1);
    
    async Task MyMethodAsync()
    {
      await _mutex.WaitAsync();
      try
      {
        ...
      }
      finally
      {
        _mutex.Release();
      }
    }
    

    Personally, I don't like the finally, so I usually write my own IDisposable to release the mutex when disposed, and my code can look like this:

    async Task MyMethodAsync()
    {
      // LockAsync is an extension method returning my custom IDisposable
      using (await _mutex.LockAsync()) 
      {
        ...
      }
    }