CareTaker22
CareTaker22

Reputation: 1300

Using Async to save a FileStream

I am trying to save a file(BitmapImage) to a certain location, but as soon as I use async & await I get an error saying the file is in use:

The process cannot access the file 'C:\Users\ ... \image1.jpg' because it is being used by another process.

My coding:

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

When I use the code without the await, the code works perfectly fine. I think it might be because another thread might be using it, but can anyone help or explain to me a work around for my issue? Thank you.

Upvotes: 4

Views: 5683

Answers (3)

juharr
juharr

Reputation: 32286

You could encode to a MemoryStream, get the byte array, use WriteAsync on the FileStream, and avoid using Task.Run altogether.

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);
}

Note that this will block your thread during the encoding and will use more memory.

Upvotes: 4

Roman
Roman

Reputation: 12201

In your case when you use Task with await another thread is used to save your encoder. But your encoder is also used by your main thread so new thread can't use it.

Change your code a little:

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);
    }
}

Now you create and save your encoder in the same task and it will use only one thread.

Upvotes: 8

Sergio
Sergio

Reputation: 2108

I think you should move the code inside the Task.Run, because it gets called inside another thread.

Upvotes: 4

Related Questions