简体   繁体   中英

Making sync code depend on async code

In my current project I am storing the state of certain objects in XML files. As i am working in a WPF project i am required to do this using async methods.

Because of that i am encountering a problem when loading up my application. I was to recreate the state of these objects from the XML files, which would have to be done async, but my content depends on the state of these objects, which in my case results in that the objects haven't been fully instantiated before i work with them.

In short: My sync methods depends on my async methods having instantiated my objects when launching my application.

Below is a bit of code that shows how i am reading an entire folder's xml files and generating a List of objects.

public List<Restaurant> restaurant = new List<Restaurant>();

public async void ReadRestaurantAsync()
{
    IStorageFolder filesFolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("folder");
    var storageFiles = await filesFolder.GetFilesAsync();

    foreach (var storageFile in storageFiles)
    {
        using (IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.Read))
        using (Stream inputStream = stream.AsStreamForRead())
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof (Restaurant));
            Restaurant objectRead = serializer.ReadObject(inputStream) as Restaurant;
            restaurant.Add(objectRead);
        }
    }
} 

Now when i call this async method from my MainPage, i can't work with the object Restaurant, as it hasn't been fully instantiated.

I guessing i will have to wait on the method being fully executed before trying to interact with Restaurant, but that seems a bit odd as well, as it ruins the whole idea about async methods.

Well, you want to await the async code, rather than waiting outright. This will keep your GUI responsive while you load the data (and perhaps show a loading message, depending on how long the loading takes).

There's no point in sync methods calling async methods and waiting . If you're doing that, you could use a sync method in the first place and save yourself the overhead. You want to be async all the way (and yes, that does mean you don't want to eg load data in a constructor - but you shouldn't be doing that anyway).

Note that you can await in an WinForms / WPF event handler just fine, so get rolling on those Load and DataBinding events etc.

In short: When you find yourself having sync code waiting on async code - your design is likely flawed. And in any case, it shows you're ignoring synchronization issues and such, which don't go away magically when you start using await - accessing global variables is still a very bad idea. Instead, you want the task to return a value (in your case, an enumerable of Restaurant ) and add those to the global list in the UI thread (that is, on the continuation that gets posted back to the synchronization context). Now, you are actually doing that, since you're handling all the async callbacks on the UI thread, but that's probably unnecessary, and in fact can be a silly overhead, making the loading take much longer.

Think async. Don't stop in the middle of the journey.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM