如何保持我的Async方法线程安全?

时间:2015-08-19 18:22:34

标签: c# multithreading asynchronous win-universal-app iot

我需要在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);
}

2 个答案:

答案 0 :(得分:4)

您可以使用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);
    }
}

答案 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后缀。