0

I'm trying to created an UWP application that when launched reads out an xml file and then displays its content in a list. I sort of managed to create a code that should do what I want, but when I run the application it tells me I shouldn't run it synchronous.

I tried many things suggested both on Youtube and Stackoverflow. Right before I posted this, I found this: How to read in an XML file asynchronously?

I believe that got me a step closer, but not there yet.

With the help of a tutorial and the above mentioned stackoverflow I got to this:

    public async Task GetCountriesFromFile()
        {


            XmlReaderSettings settings = new XmlReaderSettings
            {
                Async = true
            };
            XmlReader doc = XmlReader.Create("DummyFilepath/Countries.xml", settings);


            while (await doc.ReadAsync())
            {
                if(doc.NodeType == XmlNodeType.Element && doc.Name == "country")
                {
                    if (doc.HasAttributes)
                    {
                        var c = new Country()
                        {
                            Id = Convert.ToUInt16(doc.GetAttribute("id")),
                            Name = doc.GetAttribute("name"),
                            FromY =     Convert.ToUInt16(doc.GetAttribute("from")),
                            ToY = Convert.ToUInt16(doc.GetAttribute("to"))
                        };

                        Countries.CountriesList.Add(c);
                    }
                }
            }

        }

and my pageloaded event:

private async void PageLoaded(object sender, RoutedEventArgs e)
        {
            GetCountries getCountries = new GetCountries();
            await getCountries.GetCountriesFromFile();
        }

Ideally it happens before the page is loaded, but I guess it doesn't matter that much when I use bindings.

This now gets me an error:

System.InvalidOperationException: 'Synchronous operations should not be performed on the UI thread. Consider wrapping this method in Task.Run.'

What should I do to fix that? Thanks in advance

Tjoeker
  • 23
  • 6
  • I believe the warning gave you enough information. Have you tried wrapping the `PageLoaded` instrusctions inside `Task.Run()` ? – Little doe Sep 03 '19 at 16:20
  • @Littledoe I tried that but it gave me a different error. I did some more research now and found it has to look like this Task.Run(() => function); I think it would be better for them to specify this.. I do get another error now: my access to the file is denied. I'm escaping the backslashes as it should, I'm running VS as administrator. the file is not readonly. What else could go wrong? – Tjoeker Sep 03 '19 at 16:34
  • how about replacing the second line with fire-and-forget method? `_ = GetCountriesFromFile()` – Little doe Sep 03 '19 at 16:36
  • @littledoe do you mean like this?: await Task.Run(() => _ = getCountries.GetCountriesFromFile()); That gives me the same error. – Tjoeker Sep 03 '19 at 16:42
  • You don't have to wrap it in this case. – Little doe Sep 03 '19 at 16:47
  • Then the function I call doesn't seem to complete/ get past the await in GetCountriesFromFile. – Tjoeker Sep 03 '19 at 16:53
  • If I had to venture a guess, you are adding items to Countries.CountryList which is probably bound in the UI. Try adding the countries to a list, then add those items into Countries.Countrylist after the awaiting of the file reading. – Mark W Sep 03 '19 at 20:47
  • I'm still getting the accessdenied exception. :/ – Tjoeker Sep 04 '19 at 07:42

1 Answers1

0

How do you read xml file asynchronous?

I checked your code, the problem is that await GetCountriesFromFile will block UI thread, because you have not create new sub thread in GetCountriesFromFile method. I have edit your code please refer the following.

public async Task GetCountriesFromFile()
{
    await Task.Run(async () =>
    {
        XmlReaderSettings settings = new XmlReaderSettings
        {
            Async = true
        };

        var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Countries.xml"));
        using (var stream = await file.OpenStreamForReadAsync())
        {   
            XmlReader doc = XmlReader.Create(stream, settings);
            while (await doc.ReadAsync())
            {
                if (doc.NodeType == XmlNodeType.Element && doc.Name == "country")
                {
                    if (doc.HasAttributes)
                    {
                        var c = new Country()
                        {
                            Id = Convert.ToUInt16(doc.GetAttribute("id")),
                            Name = doc.GetAttribute("name"),
                            FromY = Convert.ToDouble(doc.GetAttribute("from")),
                            ToY = Convert.ToDouble(doc.GetAttribute("to"))
                        };

                    }
                }
            }
        }

    });
}
Nico Zhu
  • 32,367
  • 2
  • 15
  • 36