我如何保持我的异步方法线程安全



我需要在我的Windows通用应用程序中编写一个方法来写入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);
}

您可以保留带有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后缀

你可以使用AsyncEx库,它包含一个AsyncLock

假设没有大量的文件名,您可以使用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);
    }
}

最新更新