Как синхронизировать задачи?

Скажем, у меня есть метод async, который сохраняет файл:

async Task SaveToFileAsync()
{
   var file = await folder.GetFileAsync ( ...)
   var stream = file.OpenFileAsync(...)
   ///etc

}

Теперь представьте, что SaveToFileAsync вызывается дважды одновременно. Это проблема, потому что вы не можете писать в одном и том же файле одновременно

Если бы это был обычный метод, lock() исправил бы это:

void SaveToFile()
{
   lock(something)
   {
      /// code here
   }
}

Однако блокировка не допускается в методе async.

Конечно, можно вызвать Monitor.Enter() или использовать мьютекс, но эти объекты работают с потоками, а не с задачами. Поэтому они не являются ответом.

Итак, поскольку lock() не является опцией, как можно синхронизировать несколько задач? В частности, какой код я должен писать, чтобы гарантировать, что "SaveToFileAsync" вызывается только один раз за раз?

Ответы

Ответ 1

Для механизма асинхронного взаимного исключения посмотрите

  Построение примитивов для асинхронной координации, часть 6: AsyncLock

Вы можете использовать класс AsyncLock:

private readonly AsyncLock m_lock = new AsyncLock();

async Task SaveToFileAsync()
{
    using (await m_lock.LockAsync()) 
    { 
        var file = await folder.GetFileAsync(...);
        var stream = await file.OpenFileAsync(...);
        // etc
    }
}