【问题标题】:Mixing Async and Sync in same HTTP request ASP.NET Core C#在同一个 HTTP 请求中混合异步和同步 ASP.NET Core C#
【发布时间】:2019-11-13 21:00:08
【问题描述】:

在同一个 asp.net 核心 api 调用中混合异步和同步调用是不好的做法

例如下面的代码

方法 CropBlackBroderOfAnImageAsync 是一个异步方法

另一方面 SaveImageForProcessing(file, sourceFolderPath);是同步方式

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

完整的代码仓库

欢迎代码审查: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);
        }
    }

【问题讨论】:

  • “原因”是没有意义的......但否则为什么你认为有任何问题?就像你打电话给Path.GetExtension(file.FileName); 没有问题,但你自己的方法似乎引起了关注......

标签: c# asynchronous asp.net-core .net-core


【解决方案1】:

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

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

【讨论】:

  • 我不知道如何解释,但似乎不对。进行同步操作的代价就是线程不能用于其他任何事情。但当然,其他异步操作(例如对于其他用户)将继续。你是这个意思吗?
  • "如果您在异步代码中使用长同步操作,您也将冻结所有其他异步代码。"充其量需要澄清......
  • 添加了一个简短的解释
  • 人们似乎喜欢你的解释......我想如果它不完全正确并不重要,可能会让读者认为使用同步存在一些严重问题ASP.net/core 中的操作
【解决方案2】:

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

我认为您误解了异步的含义。当代码异步运行时,这意味着当前线程在等待时被释放来做其他事情。阅读文章Asynchronous programming with async and await 可能会有所帮助。它有一个关于烹饪早餐的非常有用的插图。

听起来您认为异步运行意味着代码将在其他代码运行的同时在其他地方运行。这就是所谓的“并行”。

asyncawait 的目的是让您可以轻松启动异步任务并在您准备好结果时返回它们。在您的情况下,由于您想要立即获得结果,您可以使 SaveImageForProcessing 异步,使用 CopyToAsyncawait 它。然后您可以立即使用结果。

因为您使用await,所以当您到达调用CropBlackBroderOfAnImageAsync 的线路时,您可以保证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);
    }
}

【讨论】:

    【解决方案3】:

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

    更大的问题是试图掩盖async 调用以使其看起来像sync,反之亦然。

    你可能会看这些帖子:

    sync over async

    async over sync

    【讨论】:

      猜你喜欢
      • 2022-11-11
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      • 2013-11-29
      • 2019-01-05
      • 1970-01-01
      相关资源
      最近更新 更多