I need to write a method in my Windows Universal App to write to the SD card. How can I ensure two threads do not try to write to the same file at the same time in my method below ?
public async void WriteToCard(string strFileName, IEnumerable<string> listLinesToWrite)
{
IStorageItem item = await folder.GetItemAsync(strFileName);
StorageFile file = (StorageFile)item;
await Windows.Storage.FileIO.WriteLinesAsync(file, listLinesToWrite);
}
You could keep a map with a ConcurrentDictionary
which maps each file to a SemaphoreSlim
. Then, fetch each semaphore based on the file location you'll be writing to:
private ConcurrentDictionary<string, SemaphoreSlim> fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
public async Task WriteToCardAsync(string strFileName, IEnumerable<string> listLinesToWrite)
{
var semaphoreSlim = fileLocks.GetOrAdd(strFileName, new SemaphoreSlim(1, 1));
await semaphoreSlim.WaitAsync();
try
{
IStorageItem item = await folder.GetItemAsync(strFileName);
StorageFile file = (StorageFile)item;
await Windows.Storage.FileIO.WriteLinesAsync(file, listLinesToWrite);
}
finally
{
semaphoreSlim.Release();
}
}
Side note - Use async Task
instead of async void
. I also added the Async
postfix to the methods.
You can use the AsyncEx library, which contains an AsyncLock
Assuming there won't be a huge number of filenames, you can use a ConcurrentDictionary
to associate a filename to a lock - otherwise, the dictionary size might grow unbound.
private readonly locks = new ConcurrentDictionary<string, AsyncLock>();
public async void WriteToCard(string strFileName, IEnumerable<string> listLinesToWrite)
{
var lock = locks.GetOrAdd(strFileName, () => new AsyncLock());
using (await lock.LockAsync())
{
IStorageItem item = await folder.GetItemAsync(strFileName);
StorageFile file = (StorageFile)item;
await Windows.Storage.FileIO.WriteLinesAsync(file, listLinesToWrite);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With