1

Is it bad practice to mix async and sync call in same asp.net core api call

For example in following code

Method CropBlackBroderOfAnImageAsync is an Async Method

On the other hand SaveImageForProcessing(file, sourceFolderPath); is Sync Method

Reason: that I am calling SaveImageForProcessing synchronously that I want use the result of it to execute the code in CropBlackBroderOfAnImageAsync

The complete code repo

code reviews are welcome: https://github.com/aamir-poswal/ImageCropApp/

        public async Task<(string sourceFolderPath, string destinationFolderPath)> CropBlackBorderOfAnImage(IFormFile file)
    {

        var extension = Path.GetExtension(file.FileName);
        var newFileName = Guid.NewGuid().ToString();//Create a new Name for the file due to security reasons.
        var fileNameSource = newFileName + extension;
        var sourceFolderPath = Path.Combine(Directory.GetCurrentDirectory(), "Images\\Source", fileNameSource);

        var fileNameDestination = newFileName + "Result" + extension;
        var destinationFolderPath = Path.Combine(Directory.GetCurrentDirectory(), "Images\\Destination", fileNameDestination);

        SaveImageForProcessing(file, sourceFolderPath);

        await _imageCropBlackBroderService.CropBlackBroderOfAnImageAsync(sourceFolderPath, destinationFolderPath);

        return (sourceFolderPath, destinationFolderPath);

    }

    private void SaveImageForProcessing(IFormFile file, string path)
    {
        using (var bits = new FileStream(path, FileMode.Create))
        {
            file.CopyTo(bits);
        }
    }
1
  • the "reason" makes no sense... but otherwise why do you believe there are any problems? Like you have no problems calling Path.GetExtension(file.FileName); but your own method seem to cause concerns.... Commented Nov 13, 2019 at 21:04

3 Answers 3

3

Yes, it is bad practice. If you use a long synchronous operation in your asynchronous code, you're going to freeze all the other asynchronous code as well. The reason for this is that asynchronous code usually runs in one thread. If that thread is busy waiting on a long operation, it can't handle other asynchronous code.

Instead, just use CopyToAsync, and turn your SaveImageForProcessing to an async function as well.

Sign up to request clarification or add additional context in comments.

4 Comments

I am not sure how to interpret this, but it doesn't seem right. The cost of doing a synchronous operation is simply that the thread cannot be used for anything else. But other asynchronous operations (e.g. for other users) will continue, of course. Is that what you meant?
" If you use a long synchronous operation in your asynchronous code, you're going to freeze all the other asynchronous code as well." at best need clarification...
Added a short explanation
People seem to like your explanation... I guess it does not matter if it's not exactly correct and may make reader to think that there is some serious problem with using synchronous operations in ASP.net/core
2

Reason: that I am calling SaveImageForProcessing synchronously that I want use the result of it to execute the code in CropBlackBroderOfAnImageAsync

I think you misunderstand what asynchronous means. When code runs asynchronously, it means that the current thread is freed to do other things while it is waiting. It might be helpful to read the article Asynchronous programming with async and await. It has a very helpful illustration about cooking breakfast.

It sounds like you believe that running asynchronous means that the code will run somewhere else at the same time that the rest of your code is running. That's called "parallel".

The purpose of async and await is to make it easy to start asynchronous tasks and come back to them when you're ready for the results. In your case, since you want the result right away, you can make SaveImageForProcessing asynchronous, use CopyToAsync and await it. Then you can use the result right away.

Because you use await, when you get to the line calling CropBlackBroderOfAnImageAsync, you are guaranteed that SaveImageForProcessing has entirely completed.

public async Task<(string sourceFolderPath, string destinationFolderPath)> CropBlackBorderOfAnImage(IFormFile file)
{

    var extension = Path.GetExtension(file.FileName);
    var newFileName = Guid.NewGuid().ToString();//Create a new Name for the file due to security reasons.
    var fileNameSource = newFileName + extension;
    var sourceFolderPath = Path.Combine(Directory.GetCurrentDirectory(), "Images\\Source", fileNameSource);

    var fileNameDestination = newFileName + "Result" + extension;
    var destinationFolderPath = Path.Combine(Directory.GetCurrentDirectory(), "Images\\Destination", fileNameDestination);

    await SaveImageForProcessing(file, sourceFolderPath);

    await _imageCropBlackBroderService.CropBlackBroderOfAnImageAsync(sourceFolderPath, destinationFolderPath);

    return (sourceFolderPath, destinationFolderPath);

}

private async Task SaveImageForProcessing(IFormFile file, string path)
{
    using (var bits = new FileStream(path, FileMode.Create))
    {
        await file.CopyToAsync(bits);
    }
}

Comments

2

This all depends on your application. It's totally fine to invoke a synchronous function inside of an async function. Though, you might be leaving some performance on the table. Though, if you are already doing things in an async manner, in an async function, you might as well use the async file IO methods. The code in the async function can still be asynchronous, and still execute in the correct order (which seems to be your concern), you would just await the results and use them in later lines of code.

The bigger issue is attempting to mask an async call to make it seem sync or vice versa.

You might look at these posts:

sync over async

async over sync

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.