C# 在同一HTTP请求ASP.NET核心C中混合异步和同步#

C# 在同一HTTP请求ASP.NET核心C中混合异步和同步#,c#,asynchronous,asp.net-core,.net-core,C#,Asynchronous,Asp.net Core,.net Core,在同一个asp.net核心api调用中混合使用异步和同步调用是否是错误的做法 例如,在下面的代码中 方法CropBlackBroderOfAnImageAsync是一个异步方法 另一方面,保存图像以进行处理(文件、sourceFolderPath);is同步方法 原因:我正在同步调用SaveImageForProcessing,我希望使用它的结果来执行CropBlackRoderofAnimageAsync中的代码 完全代码回购 欢迎进行代码审查: 公共异步任务CropBlackOrderOfa

在同一个asp.net核心api调用中混合使用异步和同步调用是否是错误的做法

例如,在下面的代码中

方法CropBlackBroderOfAnImageAsync是一个异步方法

另一方面,保存图像以进行处理(文件、sourceFolderPath);is同步方法

原因:我正在同步调用SaveImageForProcessing,我希望使用它的结果来执行CropBlackRoderofAnimageAsync中的代码

完全代码回购

欢迎进行代码审查:

公共异步任务CropBlackOrderOfaImage(IFormFile)
{
var extension=Path.GetExtension(file.FileName);
var newFileName=Guid.NewGuid().ToString();//由于安全原因,请为文件创建新名称。
var fileNameSource=newFileName+扩展名;
var sourceFolderPath=Path.Combine(Directory.GetCurrentDirectory(),“Images\\Source”,fileNameSource);
var filenamedstination=newFileName+“Result”+扩展名;
var destinationFolderPath=Path.Combine(Directory.GetCurrentDirectory(),“Images\\Destination”,fileNameDestination);
SaveImageForProcessing(文件,sourceFolderPath);
wait_imageCropBlackBroderService.CropBlackBroderOfAnImageAsync(sourceFolderPath,destinationFolderPath);
返回(sourceFolderPath、destinationFolderPath);
}
私有void SaveImageForProcessing(格式文件,字符串路径)
{
使用(var bits=newfilestream(路径,FileMode.Create))
{
文件.CopyTo(位);
}
}

是的,这是一种不好的做法。如果在异步代码中使用长同步操作,那么也将冻结所有其他异步代码。原因是异步代码通常在一个线程中运行。如果该线程正忙于等待一个长操作,它将无法处理其他异步代码


相反,只需使用,并将您的
SaveImageForProcessing
转换为异步函数。

是的,这是一种不好的做法。如果在异步代码中使用长同步操作,那么也将冻结所有其他异步代码。原因是异步代码通常在一个线程中运行。如果该线程正忙于等待一个长操作,它将无法处理其他异步代码


相反,只需使用,并将您的
SaveImageForProcessing
转换为异步函数。

这一切都取决于您的应用程序。在异步函数中调用同步函数完全可以。不过,您可能会在桌面上留下一些性能。不过,如果您已经在以异步方式进行操作,那么在异步函数中,您也可以使用异步文件IO方法。async函数中的代码仍然可以是异步的,并且仍然按照正确的顺序执行(这似乎是您所关心的),您只需等待结果并在以后的代码行中使用它们

更大的问题是试图屏蔽
async
调用,使其看起来像
sync
,反之亦然

你可以看看这些帖子:


这一切都取决于您的应用程序。在异步函数中调用同步函数完全可以。不过,您可能会在桌面上留下一些性能。不过,如果您已经在以异步方式进行操作,那么在异步函数中,您也可以使用异步文件IO方法。async函数中的代码仍然可以是异步的,并且仍然按照正确的顺序执行(这似乎是您所关心的),您只需等待结果并在以后的代码行中使用它们

更大的问题是试图屏蔽
async
调用,使其看起来像
sync
,反之亦然

你可以看看这些帖子:

原因:我正在同步调用SaveImageForProcessing,我希望使用它的结果来执行CropBlackRoderofAnimageAsync中的代码

我想你误解了异步的意思。当代码异步运行时,这意味着当前线程在等待时可以自由地执行其他操作。阅读这篇文章可能会有所帮助。它有一个非常有用的关于做早餐的说明

听起来您相信运行异步意味着代码将在其他地方运行,而您的其他代码正在运行。这就是所谓的“平行”

async
await
的目的是使启动异步任务变得容易,并在准备好结果时返回到它们。在您的情况下,由于您希望立即获得结果,因此可以使
SaveImageForProcessing
异步,使用
CopyToAsync
等待它。然后您可以立即使用结果

因为您使用了
wait
,当您到达调用
cropblackbroderofanimagesasync
的线路时,可以保证
SaveImageForProcessing
已完全完成

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);
    }
}
公共异步任务CropBlackOrderOfaImage(IFormFile)
{
var extension=Path.GetExtension(file.FileName);
var newFileName=Guid.NewGuid().ToString();//由于安全原因,请为文件创建新名称。
var fileNameSource=newFileName+扩展名;
var sourceFolderPath=Path.Combine(Directory.GetCurrentDirectory(),“Images\\Source”,fileNameSource);
var filenamedstination=newFileName+“Result”+扩展名;
var destinationFolderPath=Path.Combine(Directory.GetCurrentDirectory(),“Images\\Destination”,fileNameDestination);
等待SaveImageForProcessing(文件,sourceFolderPath);
wait_imageCropBlackBroderService.CropBlackBroderOfAnImageAsync(sourceFolderPath,destinationFolderPath);
返回(sourceFolderPath、destinationFolderPath);
}
专用异步任务SaveImageForProcessing(格式化文件,字符串路径)
{
使用(var位=新文件流(路径,Fil
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);
    }
}