使用Windows运行时编写文件时,所有方法都是异步的。是否可以确保在此方案中按顺序完成文件访问和写入操作?
例如,如果我有一个可以从多个其他异步和可能并行代码调用的日志记录类,我如何确保记录器实际同步写入文件?
由于使用了async / await,我不能只是锁定文件访问权限,如:
lock (locker)
{
var storageFile = await GetStorageFileAsync();
await FileIO.AppendTextAsync(storageFile, text);
}
我想知道来自Dataflow TPL的BufferBlock是否可以在这种情况下用于序列化写入,但我不确定如何设置它。我认为它看起来像:
static readonly BufferBlock<string> LogBuffer = new BufferBlock<string>();
public async static Task LogAsync(string message)
{
LogBuffer.Post(message);
string messageToWrite;
while (LogBuffer.TryReceive(out messageToWrite))
{
var storageFile = await GetStorageFileAsync();
await FileIO.AppendTextAsync(storageFile, messageToWrite);
}
}
我可能正在混合使用异步和多线程编程,但我认为在使用Tasks时,您无法确定将调用哪个代码线程。在这种情况下,我想确保一次只有一个线程可以访问该文件。我正朝着正确的方向前进吗?
答案 0 :(得分:3)
您想要的是 synchronized 异步代码。默认情况下,异步代码是顺序的(如果您await
一个操作,则该方法将不会继续,直到该操作完成);你希望它同步。不是&#34;同步&#34;,或者;你仍然希望它是异步的。
您可以使用SemaphoreSlim
作为async
- 兼容的lock
来同步异步代码:
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
...
await _semaphore.WaitAsync();
try
{
var storageFile = await GetStorageFileAsync();
await FileIO.AppendTextAsync(storageFile, text);
}
finally
{
_semaphore.Release();
}
也就是说,如果希望其余代码在排队写入后立即继续而不是(异步)等待写入完成,则可能更喜欢ActionBlock
。< / p>