When does a file used to display an image in a ListView get released?

Will.ItraxWill.Itrax CAMember ✭✭✭

In our app, we draw a sketch using SkiaSharp. OnSave, the sketch is saved to a file and the commands used by SkiaSharp to draw the image are saved to SQLite. That way, at a later time, in a LoadView, we can have a list of sketches to chose from in a ListView.

The sketches are displayed via a path to the images like this:
<Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Source="{Binding PhotoPath}" />

When an image is tapped that info is passed back to the SketchView where the details for creating the image are read from the table and displayed. If I make a small change (i.e. take very little time) and then save the Image over the previous version, sometimes I get the following exception:
Exception in SketchView.OnSaveButtonClicked: System.IO.IOException: The process cannot access the file <the file that I am trying to overwrite> because it is being used by another process.

It seems that if I spend more time adding to the sketch, or wait longer before tapping Save, that it is less likely to throw this exception.

I tried to only show the file name in the LoadView (i.e. no image). It is not a user friendly UI then, but it did not result in the Exception after around a dozen tries.

All that leads me to think that the LoadView hangs onto the images long after the View is closed. What can I do to free up that memory? What else should I consider?
Thanks!

Answers

  • ColeXColeX Member, Xamarin Team Xamurai

    Can you post the detailed code that reproducing this error ?

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @ ColeX Thanks for your interest. It seems that my boss came across an alternate way to load images which avoids the Exception. So, I do not have the time to create a proper repro. I will try to give more details for the code that failed and the change that seems to work. (I am not more positive as the exception did not always appear. When it did, there seemed to be less time between selecting the image, making an edit, and saving over the image.)

    Set up:
    SketchView uses SkiaSharp to create a Sketch. The Save button saves the Image and also serializes and saves the Skia commands that can be used to recreate the image in Skia and resume sketching. A Load button opens the LoadView which gets a List of Sketch info. Each selected record has a path to a corresponding Sketch image. They get displayed in a ListView via a reference to the path like this:
    <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Source="{Binding PhotoPath}" />
    That way the user can see the images and select the one they want to continue sketching. Tapping the desired image sends the necessary data back to SketchView so the image can be recreated for further sketching via Skia. It also closes the LoadView via:
    await SLVM.pg.Navigation.PopModalAsync();

    Back in SketchView, the commands to recreate the sketch are loaded from SQLite into a string which gets deserialized and then displayed via
    canvasView.InvalidateSurface();
    If I then add something to the sketch so that the Save button is enabled, and tap Save, quite often I get the Exception. Since the exception mentions the path to the image that I had just selected, and complains about
    it is being used by another process.
    and the only other process that did anything with the image is the LoadView, I deduce that it is the culprit.

    The Alternative:
    Instead of displaying the image in LoadView by referring to the image's path, we do this:
    foreach (SketchPhoto sp in lsp) { var memoryStream = new MemoryStream(); using (var fileStream = new FileStream(sp.PhotoPath, FileMode.Open, FileAccess.Read)) { fileStream.CopyTo(memoryStream); } memoryStream.Position = 0; sp.FileImg = ImageSource.FromStream(() => memoryStream); }
    (side question: how do I retain indents when posting code?)
    then the images get displayed via:
    <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Source="{Binding FileImg}" />
    With this set up, when I select an image in LoadView, display it in SketchView, add a line and Save it, I do not get the exception. Maybe I've been lucky so far.

  • ColeXColeX Member, Xamarin Team Xamurai

    how do I retain indents when posting code?

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @ColeX Oh. I was selecting Code; getting the two quotes and pasting the code between them. The steps that work are to Paste the code; select it; select Code. I did not think of that. Thanks!

    A Question:
    In XAML when I write this:
    <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Source="{Binding PhotoPath}" />
    is the Image at PhotoPath opened in ReadWrite mode? If so, is there a way in XAML to force it to open in Read mode, or should I stick with the method I described earlier?
    Thanks!

Sign In or Register to comment.