线程安全异步方法
Thread safe async method
假设我们有以下 class:
public class StreamDocumentRepresentation: DocumentRepresentation
{
private readonly IFileStorageService _fileStorageService;
private readonly MemoryStream _documentStream;
private string _fileName;
public StreamDocumentRepresentation(MemoryStream documentStream, IFileStorageService fileStorageService)
{
_documentStream = documentStream;
_fileStorageService = fileStorageService;
}
public override async Task<string> GetDocumentUriAsync()
{
if (string.IsNullOrWhiteSpace(_fileName))
{
await UploadDocument();
}
return _fileName;
}
private async Task UploadDocument()
{
_fileName = $"{Guid.NewGuid()}.pdf";
await _fileStorageService.UploadFile(_fileName, _documentStream);
}
}
它将文档表示为内存流,并在我们想要获取文件的URI 时将其上传到文件存储。当我们上传文件时,fileName(也是URI)被创建并存储,所以当GetDocumentUriAsync
第二次调用时,它不会再次上传文件,只是returns URI现有的。
问题是如何使这个 class 线程安全以确保文件只上传一次?
The question is how to make this class thread safe to make sure, that the file will be uploaded only once?
您可以使用 SemaphoreSlim
作为一种异步兼容锁:
public class StreamDocumentRepresentation: DocumentRepresentation
{
private readonly SemaphoreSlim _mutex = new(1);
private readonly IFileStorageService _fileStorageService;
private readonly MemoryStream _documentStream;
private string _fileName;
public override async Task<string> GetDocumentUriAsync()
{
await _mutex.WaitAsync();
try
{
if (string.IsNullOrWhiteSpace(_fileName))
await UploadDocument();
return _fileName;
}
finally
{
_mutex.Release();
}
}
private async Task UploadDocument()
{
var fileName = $"{Guid.NewGuid()}.pdf";
await _fileStorageService.UploadFile(fileName, _documentStream);
_fileName = fileName;
}
}
旁注:我修改了 UploadDocument
一点,以便在上传失败时不会设置 _fileName
。
假设我们有以下 class:
public class StreamDocumentRepresentation: DocumentRepresentation
{
private readonly IFileStorageService _fileStorageService;
private readonly MemoryStream _documentStream;
private string _fileName;
public StreamDocumentRepresentation(MemoryStream documentStream, IFileStorageService fileStorageService)
{
_documentStream = documentStream;
_fileStorageService = fileStorageService;
}
public override async Task<string> GetDocumentUriAsync()
{
if (string.IsNullOrWhiteSpace(_fileName))
{
await UploadDocument();
}
return _fileName;
}
private async Task UploadDocument()
{
_fileName = $"{Guid.NewGuid()}.pdf";
await _fileStorageService.UploadFile(_fileName, _documentStream);
}
}
它将文档表示为内存流,并在我们想要获取文件的URI 时将其上传到文件存储。当我们上传文件时,fileName(也是URI)被创建并存储,所以当GetDocumentUriAsync
第二次调用时,它不会再次上传文件,只是returns URI现有的。
问题是如何使这个 class 线程安全以确保文件只上传一次?
The question is how to make this class thread safe to make sure, that the file will be uploaded only once?
您可以使用 SemaphoreSlim
作为一种异步兼容锁:
public class StreamDocumentRepresentation: DocumentRepresentation
{
private readonly SemaphoreSlim _mutex = new(1);
private readonly IFileStorageService _fileStorageService;
private readonly MemoryStream _documentStream;
private string _fileName;
public override async Task<string> GetDocumentUriAsync()
{
await _mutex.WaitAsync();
try
{
if (string.IsNullOrWhiteSpace(_fileName))
await UploadDocument();
return _fileName;
}
finally
{
_mutex.Release();
}
}
private async Task UploadDocument()
{
var fileName = $"{Guid.NewGuid()}.pdf";
await _fileStorageService.UploadFile(fileName, _documentStream);
_fileName = fileName;
}
}
旁注:我修改了 UploadDocument
一点,以便在上传失败时不会设置 _fileName
。