图片已保存损坏的异步方式

时间:2019-02-11 15:19:38

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

  

为什么?当我保存2张图片时,第一个保存已损坏,第二个未保存   全部保存

     

我想保存文件而不卡住客户端(Task.Run),并且   不会卡住服务器(异步等待)

Task.Run(async () => {    
            foreach (var item in Images) 
            {
                // item.File is IFormFile array
                await SaveFile(item.FileSavePath, item.File);
            }
});

   public static async Task SaveFile(string filePath, IFormFile file)
        {
            string folderPath = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(folderPath))
                Directory.CreateDirectory(folderPath);

            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                await file.CopyToAsync(fileStream);
            }
        }

1 个答案:

答案 0 :(得分:1)

如果不等待Task.Run,那么几乎可以肯定会在实际的SaveFile任务完成之前返回该操作。当操作超出范围时,它将带走其所有范围变量,包括从帖子主体绑定的IFormFile实例。这将导致写入被过早取消,从而使您留下损坏的文件(因为在写入过程中流被破坏了)。将引发异常,但是由于您正在新线程中运行,因此该异常不会在请求管道中冒泡,并且会被有效吞咽。

长而短,请等待您打给Task.Run的电话。但是,一旦这样做,那么在这里使用Task.Run实际上是没有意义的。因此,最好完全摆脱它。相反,只需解开所有任务,然后等待Task.WhenAll

var tasks = new List<Task>();
foreach (var item in Images) 
{
    // item.File is IFormFile array
    tasks.Add(SaveFile(item.FileSavePath, item.File));
}
await Task.WhenAll(tasks);

任务热返回或已启动。这样,等待每个项目保存在foreach中将导致串行处理任务。仅将它们保存到列表中,就可以使它们全部并行启动和运行。然后,您只需要等待列表中所有任务的完成即可避免操作返回,直到工作完成为止。