简体   繁体   English

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

[英]Image saved corrupted async way

Why? 为什么? when i save 2 images, the first saved corrupted and the second not saved at all 当我保存2张图像时,第一个保存损坏,第二个根本不保存

i want to save file without stuck the client(Task.Run) and without stuck the server(async await) 我想保存文件而不卡住客户端(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);
            }
        }

If the Task.Run is not awaited, then the action will almost assuredly return before the actual SaveFile tasks have finished. 如果未等待Task.Run ,则几乎可以肯定会在实际的SaveFile任务完成之前返回操作。 When the action goes out of scope, it takes all its scoped variables with it, including your IFormFile instances that were bound from the post body. 当动作超出范围时,它将带走所有其范围的变量,包括从帖子主体绑定的IFormFile实例。 This will cause the write to be prematurely cancelled, leaving you with a corrupted file (since the stream is destroyed mid-write). 这将导致写入被过早取消,从而使您留下损坏的文件(因为在写入过程中流被破坏了)。 An exception will be raised, but because you're running inside a new thread, it won't bubble up through the request pipeline, and is effectively swallowed. 将会引发一个异常,但是由于您正在新线程中运行,因此它不会在请求管道中冒泡,并且会被有效吞咽。

Long and short, await your call to Task.Run . 总之,请等待您对Task.Run的调用。 However, once you do that, then there's effectively no point in using Task.Run here. 但是,一旦这样做,使用Task.Run实际上就没有意义了。 So, you're better off just getting rid of it entirely. 因此,最好完全摆脱它。 Instead, just fire off all the tasks and then await Task.WhenAll : 相反,只需解雇所有任务,然后等待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);

Tasks return hot, or already started. 任务热返回或已开始。 As such, awaiting each item save in the foreach would result in the tasks being processed in serial. 这样,等待每个项目保存在foreach中将导致串行处理任务。 Just saving them to a list, causes them all to be started and run essentially in parallel. 仅将它们保存到列表中,就可以使它们全部并行启动和运行。 Then, you simply await the completion of all tasks in the lists to keep the action from returning until the work is finished. 然后,您只需要等待列表中所有任务的完成即可避免操作返回,直到工作完成为止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM