JohnyDgoode
JohnyDgoode

Reputation: 1563

In Windows8,How to treat an asynchronous method as a synchronous method?

The StoreBitmapImage is synchronous function to store bitmap images to disk. But when I compile, I get System.AggregateException, what am I doing wrong?

public static void StoreBitmapImage(string uri,string fileName)
    {
        HttpClient httpClient = new HttpClient();
        IRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
        Stream responseStream = httpClient.GetStreamAsync(new Uri(uri)).Result;//Get BMP from web

        Byte[] buffer = new byte[500];
        int read;

        do
        {
            read = responseStream.ReadAsync(buffer, 0, buffer.Length).Result;
            randomAccessStream.WriteAsync(buffer.AsBuffer()).GetResults();

        } while (read != 0);//convert responseStream into bytes

        randomAccessStream.FlushAsync().GetResults();
        randomAccessStream.Seek(0);

        StorageFolder folder = ApplicationData.Current.RoamingFolder;//prepare folder

        StorageFile file = null;
        if (folder != null && buffer != null)
            file = folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting).GetResults();
        else
            return;

        using (IRandomAccessStream rStream = file.OpenAsync(FileAccessMode.ReadWrite).GetResults())
        using (IOutputStream oStream = rStream.GetOutputStreamAt(0))
        {
            DataWriter writer = new DataWriter(oStream);
            writer.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
            writer.WriteBytes(buffer);
            writer.StoreAsync().GetResults();
        }//write to folder
    }

Upvotes: 1

Views: 1137

Answers (4)

Stephen Cleary
Stephen Cleary

Reputation: 456577

One of the primary guidelines of async code is "async all the way down"; in other words, don't block on async code.

Keeping with this guideline, you should make your method async:

public static async Task StoreBitmapImage(string uri, string fileName)
{
  HttpClient httpClient = new HttpClient();
  IRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
  Stream responseStream = await httpClient.GetStreamAsync(new Uri(uri)); //Get BMP from web

  Byte[] buffer = new byte[500];
  int read;

  do
  {
    read = await responseStream.ReadAsync(buffer, 0, buffer.Length);
    await randomAccessStream.WriteAsync(buffer.AsBuffer());
  } while (read != 0);//convert responseStream into bytes

  await randomAccessStream.FlushAsync();
  randomAccessStream.Seek(0);

  StorageFolder folder = ApplicationData.Current.RoamingFolder;//prepare folder

  StorageFile file = null;
  if (folder != null && buffer != null)
    file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
  else
    return;

  using (IRandomAccessStream rStream = await file.OpenAsync(FileAccessMode.ReadWrite))
  using (IOutputStream oStream = rStream.GetOutputStreamAt(0))
  {
    DataWriter writer = new DataWriter(oStream);
    writer.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
    writer.WriteBytes(buffer);
    await writer.StoreAsync();
  }//write to folder
}

Upvotes: 1

Jürgen Bayer
Jürgen Bayer

Reputation: 3023

You are trying to invoke GetResults on the IAsyncOperation object you get as the result of invoking an async method. That will fail in most cases since the async operation did not complete when the async method returns. The AggregateException you get is probably the result of trying to get the result to early. You could use following code to invoke an async method synchronously:

Task<StorageFile> task = folder.CreateFileAsync(fileName,
   CreationCollisionOption.ReplaceExisting).AsTask();

 // Read the result which will synchronously wait for the async operation
 StorageFile file = task.Result;

Since invoking async code synchronously is not allowed by the Microsoft guidance for Windows Store apps and an application using such code would probably fail the certification a better solution would be to make your method async as well and invoke the async methods using await. That of course involves that your method itself is invoked using await. But if you design a new app this should not be a problem at all.

In your defence: Invoking async code synchronously is probably okay for "proof of concept" apps or Desktop apps that make use of WinRT types (referencing the appropriate .winmd files).

Upvotes: 1

Igor Kulman
Igor Kulman

Reputation: 16361

Trying to do such operation synchronosly is not a good practice. Saving a file from web can be done quite easy in WinRT, take a look at https://winrtxamltoolkit.codeplex.com/SourceControl/changeset/view/0657c67a93d5#WinRTXamlToolkit%2fNet%2fWebFile.cs.

Upvotes: 1

Mayank
Mayank

Reputation: 8852

System.AggregateException means there are multiple Exceptions in your code. Can you explain what do you mean by How to treat an asynchronous method as a synchronous method?

Upvotes: 1

Related Questions