ng-R
ng-R

Reputation: 757

Wait for Async method to complete

I am creating a windows phone app, where on launch of the app, I create an xml in installation location of the app and then I call a method, which initializes the User settings class with the values in xml. In the beginning, I check if the xml is already available, if it is not, I create an xml, if it is present, it is read and User settings are initialized. Here is the code in OnLaunched event of App.xaml.cs

var isCreateFileSuccessfull = CreateOrInitializeMainXml();

UserSettings.GetInstance().GetValuesFromXmlDoc(HASHNOTESDOC);

where HASHNOTESDOC is of type XDocument.

The body of the method is as:

async private void CreateOrInitializeMainXml()
    {
        try 
        { 
            StorageFolder InstallationFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
            string hashnotesFile = @"Assets\hashnotes.xml";

            StorageFile file = await InstallationFolder.GetFileAsync("hashnotes.xml");
            bool fileExists = await FileExists(InstallationFolder, "hashnotes.xml");

            if (!fileExists)
            {
                await file.CopyAsync(InstallationFolder);
            }

            StorageFile hashNoteXml = await InstallationFolder.GetFileAsync(hashnotesFile);
            Stream hashNotesStream = await hashNoteXml.OpenStreamForWriteAsync();
            hashNotesXDocument = XDocument.Load(hashNotesStream);

            hashNotesXDocument.Save(hashNotesStream);

        }
        catch
        {

        }
    }

Problem is that, since the above method is an async method, even before it finishes, control tries to execute the line

UserSettings.GetInstance().GetValuesFromXmlDoc(HASHNOTESDOC);

and by this time HASHNOTESDOC is null. How can I wait till the HASHNOTESDOC is initialized and only then go and read the user settings?

Upvotes: 3

Views: 2181

Answers (1)

Daniel Mann
Daniel Mann

Reputation: 58980

You have to make the return type of CreateOrInitializeMainXml a Task and await the Task in the event handler, which also must be async:

So, change your method declaration:

private async Task CreateOrInitializeMainXml() { ... }

And the consuming code:

var isCreateFileSuccessfull = await CreateOrInitializeMainXml();

The general rule for async void is that you should only use it for event handlers. async void is "fire-and-forget": you cannot await it, and exceptions thrown in async void methods may be uncatchable and crash your application.

The async keyword has been described as "viral" -- when you start using it, it will spread through your application as more and more things become async in order to await other async methods. This is perfectly natural and fine. Don't fight it.

Upvotes: 6

Related Questions