Bob Machine
Bob Machine

Reputation: 141

Asynchronous call to WriteAsync, how do i know when it’s complete?

Im writing a file to IsolatedStorageFile with an asynchronous call

async void  Base64ToImage()
{
   byte[] data;
   using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
   {
     using (IsolatedStorageFileStream isfs = isf.OpenFile("image.p64", FileMode.Open, FileAccess.ReadWrite))
      {
         data = new byte[isfs.Length];
         isfs.Read(data, 0, data.Length);
         isfs.Close();
      }

     using (IsolatedStorageFileStream stream = isf.OpenFile("newReConvertedFile.png", FileMode.Create))
     {
         await stream.WriteAsync(data, 0, data.Length);

 ///////////////////The problem is here, how would i know when WriteAsync is complete to then fire the reload method?
        //reLoadFile();
      }
   }
}

i need to know when that WriteAsync is complete to reload that file in another method, how would i go about doing that?

Edit:

Actually my first idea was to save the file to isostorage then sen the image uri to that file, but you can't set uri to isostorage for images or at least i couldn't get to display

My initial thought was to await the method call to reload the file but i get an error “??? does not return a task and cannot be awaited. Consider changing it to return” but I’m not sure how to go about doing this.

The idea here is to convert several images to Base64 (SQLite db), but then load only the selected ones, to display.

the reLoadFile method is as follows

async void reLoadFile()
{
    byte[] newFile;
    using (IsolatedStorageFile newFileLoc = IsolatedStorageFile.GetUserStoreForApplication())
    {
        using (IsolatedStorageFileStream newFileStream = newFileLoc.OpenFile("newReConvertedFile.png", FileMode.Open, FileAccess.ReadWrite))
        {
            newFile = new byte[newFileStream.Length];
            newFileStream.Read(newFile, 0, newFile.Length);
            newFileStream.Close();

            var ms = new MemoryStream(newFile); 
            var image = new BitmapImage(); 
            image.SetSource(ms); 
            theImage.Source = image; 
        }
     }
 }

I've been searching the posts but i couldn't fine a way to get it to work, because if i call it straight away i get an exception. What i need to do is open the file convert it from base64 to .png then load the .png file after it has been saved. If someone could help me out i would appreciate it.

Thanks Bob.

Upvotes: 3

Views: 4156

Answers (3)

Scott Chamberlain
Scott Chamberlain

Reputation: 127593

1) reloadFile does not need to be async you only need to use that when you use the await keyword inside the method

2) BaseTo64Image needs to be declared as async Task Base64ToImage() otherwise the callers of Base64ToImage() will not be able to tell when it finishes.

3) isfs.Read(data, 0, data.Length); is bad, just because you requested data.Length bytes does not mean you will get data.Length read in, you need to check the int read returns and loop or use CopyTo(Stream) to copy to another stream.

4) (to actually answer your question) the keyword await will stop the function from processing and wait till the function is complete. When you hit the await keyword your Base64ToImage() function will return at that point with a Task representing the rest of the code in that function, it is up to you what you do with that Task returned from the function.

Here is a simplified version of your code using all of the suggestions

async Task Base64ToImage()
{
    using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
    using (IsolatedStorageFileStream stream = isf.OpenFile("newReConvertedFile.png", FileMode.Create))
    using (IsolatedStorageFileStream isfs = isf.OpenFile("image.p64", FileMode.Open, FileAccess.ReadWrite))
    {
         await isfs.CopyToAsync(stream);
    }      

    await ReLoadFile();
}

async Task ReLoadFile()
{


    using (IsolatedStorageFile newFileLoc = IsolatedStorageFile.GetUserStoreForApplication())
    {
        using (IsolatedStorageFileStream newFileStream = newFileLoc.OpenFile("newReConvertedFile.png", FileMode.Open, FileAccess.ReadWrite))
        {
            var ms = new MemoryStream();
            var image = new BitmapImage();
            await newFileStream.CopyToAsync(ms);

            ms.Position = 0;    
            image.SetSource(ms); 
            theImage.Source = image; 
        }
     }
 }

However if that is all you are doing, and you are just using newReConvertedFile.png as a temporary file you can simplify your code to

async Task Base64ToImage()
{
    using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
    using (IsolatedStorageFileStream isfs = isf.OpenFile("image.p64", FileMode.Open, FileAccess.ReadWrite))
    {
         var ms = new MemoryStream();
         var image = new BitmapImage();
         await isfs.CopyToAsync(ms);

         ms.Position = 0;
         image.SetSource(ms); 
         theImage.Source = image; 
    }      
}

Upvotes: 4

Stephen Cleary
Stephen Cleary

Reputation: 456887

The WriteAsync method is complete when its returned Task completes.

To wait for the task to complete, just await it:

await stream.WriteAsync(data, 0, data.Length);
// WriteAsync is complete.

Upvotes: 2

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73492

Just call it in next line. await will wait asynchronously till WriteAsync completes. That's what the beauty of "async/await" which lets you to write asynchronous code that looks synchronous.

 using (IsolatedStorageFileStream stream = isf.OpenFile("newReConvertedFile.png", FileMode.Create))
 {
     await stream.WriteAsync(data, 0, data.Length);
     reLoadFile();
  }

Am I missing something?

Upvotes: 1

Related Questions