我需要在Windows Universal App中编写一个方法来写入SD卡。如何确保两个线程不会尝试在我的方法中同时写入同一个文件?
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);
}
答案 0 :(得分:4)
假设不存在大量文件名,您可以使用ConcurrentDictionary
将文件名与锁相关联 - 否则,字典大小可能会不受约束。
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);
}
}
答案 1 :(得分:3)
您可以使用ConcurrentDictionary
保留地图,将每个文件映射到SemaphoreSlim
。然后,根据您要写入的文件位置获取每个信号量:
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();
}
}
旁注 - 使用async Task
代替async void
。我还在方法中添加了Async
后缀。