【问题标题】:Using Async to save a FileStream使用 Async 保存 FileStream
【发布时间】:2017-12-03 02:11:54
【问题描述】:

我正在尝试将文件 (BitmapImage) 保存到某个位置,但一旦我使用 asyncawait,我就会收到一条错误消息,提示该文件正在使用中:

进程无法访问文件'C:\Users\ ... \image1.jpg',因为 它正被另一个进程使用。

我的编码:

BitmapImage image = new BitmapImage(new Uri(oldImagePath));
var encoder = new JpegBitmapEncoder() { QualityLevel = 17 };
encoder.Frames.Add(BitmapFrame.Create(image));

using (var filestream = new FileStream(GetImageLocation(), FileMode.Create))
    await Task.Run(() => encoder.Save(filestream)); //Error here

当我使用代码没有await 时,代码工作得非常好。我认为这可能是因为另一个线程可能正在使用它,但是任何人都可以帮助或向我解释解决我的问题的方法吗?谢谢。

【问题讨论】:

  • 您可以编码到内存流获取字节数组,然后在FileStream 上使用WriteAsync,并完全避免使用Task.Run
  • @juharr 听起来很有趣,我会尝试一下,谢谢。
  • @juharr 您还可以将您的解决方案发布为可能需要它的其他人的替代解决方案吗?我也可以将它与当前选择的答案一起使用,我的图像加载速度很慢,我的 Image 控件在图像之前加载,所以没有图像显示......(也是因为不同的线程在做这项工作)。
  • 你的线程在CPU绑定的编码过程中会被阻塞,但这应该比IO少得多。您甚至可以考虑不使用await,具体取决于此代码的运行位置(如果在 UI 线程中,那么您希望保留它以避免在保存期间锁定 UI)。

标签: c# wpf async-await


【解决方案1】:

当您将Taskawait 一起使用时,另一个线程用于保存您的encoder。但是你的编码器也被你的主线程使用,所以新线程不能使用它。

稍微修改一下代码:

await Task.Run(() => 
{ 
    using (var filestream = new FileStream(GetImageLocation(), FileMode.Create))
    {      
         BitmapImage image = new BitmapImage(new Uri(oldImagePath));
         var encoder = new JpegBitmapEncoder() { QualityLevel = 17 };
         encoder.Frames.Add(BitmapFrame.Create(image));
         encoder.Save(filestream);
    }
}

现在您在同一个任务中创建并保存您的encoder,它将只使用一个线程。

【讨论】:

  • 为什么不将其全部移到 Task.Run 调用中?
【解决方案2】:

我认为您应该将代码移动到 Task.Run 中,因为它会在另一个线程中被调用。

【讨论】:

  • 这提供了什么,而罗马的答案却没有?
  • 我们同时回复
【解决方案3】:

您可以编码为MemoryStream,获取字节数组,在FileStream 上使用WriteAsync,并完全避免使用Task.Run

BitmapImage image = new BitmapImage(new Uri(oldImagePath));
var encoder = new JpegBitmapEncoder() { QualityLevel = 17 };
encoder.Frames.Add(BitmapFrame.Create(image));
using (var mem = new MemoryStream())
using (var filestream = new FileStream(GetImageLocation(), FileMode.Create))
{
    encoder.Save(mem);
    var data = mem.ToArray();
    await filestream.WriteAsync(date, 0, data.Length);
}

请注意,这将在编码期间阻塞您的线程并使用更多内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    相关资源
    最近更新 更多