diff --git a/src/Libraries/Nop.Services/Media/PictureService.cs b/src/Libraries/Nop.Services/Media/PictureService.cs index dbcfbfc17ed..41e8ea8aa3b 100644 --- a/src/Libraries/Nop.Services/Media/PictureService.cs +++ b/src/Libraries/Nop.Services/Media/PictureService.cs @@ -578,21 +578,23 @@ public virtual async Task GetPictureSeNameAsync(string name) if (await GeneratedThumbExistsAsync(thumbFilePath, thumbFileName)) return (await GetThumbUrlAsync(thumbFileName, storeLocation), picture); - //the named semaphore helps to avoid creating the same files in different threads, + //the named mutex helps to avoid creating the same files in different threads, //and does not decrease performance significantly, because the code is blocked only for the specific file. - using (var semaphore = new Semaphore(1, 1, thumbFileName)) + //you should be very careful, mutexes cannot be used in with the await operation + //we can't use semaphore here, because it produces PlatformNotSupportedException exception on UNIX based systems + using (var mutex = new Mutex(false, thumbFileName)) { - semaphore.WaitOne(); + mutex.WaitOne(); try { //check, if the file was created, while we were waiting for the release of the mutex. - if (!await GeneratedThumbExistsAsync(thumbFilePath, thumbFileName)) + if (!GeneratedThumbExistsAsync(thumbFilePath, thumbFileName).Result) { - pictureBinary ??= await LoadPictureBinaryAsync(picture); + pictureBinary ??= LoadPictureBinaryAsync(picture).Result; if ((pictureBinary?.Length ?? 0) == 0) - return showDefaultPicture ? (await GetDefaultPictureUrlAsync(targetSize, defaultPictureType, storeLocation), picture) : (string.Empty, picture); + return showDefaultPicture ? (GetDefaultPictureUrlAsync(targetSize, defaultPictureType, storeLocation).Result, picture) : (string.Empty, picture); byte[] pictureBinaryResized; if (targetSize != 0) @@ -605,18 +607,18 @@ public virtual async Task GetPictureSeNameAsync(string name) Size = CalculateDimensions(image.Size(), targetSize) })); - pictureBinaryResized = await EncodeImageAsync(image, imageFormat); + pictureBinaryResized = EncodeImageAsync(image, imageFormat).Result; } else //create a copy of pictureBinary pictureBinaryResized = pictureBinary.ToArray(); - await SaveThumbAsync(thumbFilePath, thumbFileName, picture.MimeType, pictureBinaryResized); + SaveThumbAsync(thumbFilePath, thumbFileName, picture.MimeType, pictureBinaryResized).Wait(); } } finally { - semaphore.Release(); + mutex.ReleaseMutex(); } } diff --git a/src/Libraries/Nop.Services/Media/RoxyFileman/DatabaseRoxyFilemanService.cs b/src/Libraries/Nop.Services/Media/RoxyFileman/DatabaseRoxyFilemanService.cs index 9391ad83db1..b22668a5652 100644 --- a/src/Libraries/Nop.Services/Media/RoxyFileman/DatabaseRoxyFilemanService.cs +++ b/src/Libraries/Nop.Services/Media/RoxyFileman/DatabaseRoxyFilemanService.cs @@ -278,11 +278,13 @@ protected virtual async Task SavePictureByVirtualPathAsync(Picture picture, int if (_fileProvider.FileExists(thumbFilePath)) return; - //the named semaphore helps to avoid creating the same files in different threads, + //the named mutex helps to avoid creating the same files in different threads, //and does not decrease performance significantly, because the code is blocked only for the specific file. - using var semaphore = new Semaphore(1, 1, thumbFileName); + //you should be very careful, mutexes cannot be used in with the await operation + //we can't use semaphore here, because it produces PlatformNotSupportedException exception on UNIX based systems + using var mutex = new Mutex(false, thumbFileName); - semaphore.WaitOne(); + mutex.WaitOne(); try { @@ -302,7 +304,7 @@ protected virtual async Task SavePictureByVirtualPathAsync(Picture picture, int Size = CalculateDimensions(size, targetSize) })); - pictureBinaryResized = await EncodeImageAsync(image, imageFormat); + pictureBinaryResized = EncodeImageAsync(image, imageFormat).Result; } else { @@ -311,12 +313,12 @@ protected virtual async Task SavePictureByVirtualPathAsync(Picture picture, int } //save - await _fileProvider.WriteAllBytesAsync(thumbFilePath, pictureBinaryResized); + _fileProvider.WriteAllBytesAsync(thumbFilePath, pictureBinaryResized).Wait(); } } finally { - semaphore.Release(); + mutex.ReleaseMutex(); } }