locked
File Read Async during Page Load results in a deadlock.

    Question

  • Hi experts,

    In my Universal app, I am reading a big data structure upon MainPage load as I need to fill some data in my MainPage with the contents from the file.

    FYI, I serialize my data when I read and write to a file and store in appdata as you can see that from my code snippet. However, I see that some times in Windows app, I see the Page load hangs forever and in my Windows Phone App, it never works at all.

    I could be wrong but I kind of suspect that it could be the await from the ReadContent() and the UI that is not behaving well with each other. On windows it works like 90% of the time, but in Windows phone, it never worked.

    Any idea on how to handle this case better would be very helpful and appreciated.

         

    private void Page_Loaded(object sender, RoutedEventArgs e)

    { try { if ((Application.Current as App).ApplicationDataSource == null) { ApplicationUtilities.LoadDataFromDataSource(); } this.lstMatches.ItemsSource = (Application.Current as App).ApplicationDataSource.Matches; this.lstTeams.ItemsSource = (Application.Current as App).ApplicationDataSource.Teams; } catch (Exception ex) { string exception = ex.Message.ToString(); throw ex; } } } public static void LoadDataFromDataSource() { try { UltimateCricketScorerDataSource dataSource = new UltimateCricketScorerDataSource(); Task<ReadResults> loadResults = ReadContent<UltimateCricketScorerDataSource>(myKey, dataSource.GetType()); if (loadResults.Result != null && loadResults.Result.Success == true) { dataSource = loadResults.Result.Result as UltimateCricketScorerDataSource; (Application.Current as App).ApplicationDataSource = dataSource; } else { //File Not Found. Create it for the first time. ApplicationUtilities.CreateFileOnFirstLoad(); } //return loadResults; } catch (Exception ex) { string excep = ex.ToString(); throw; } } private static async Task<ReadResults> ReadContent<type>(string Key, Type t) { var rr = new ReadResults(); try { var ms = new MemoryStream(); DataContractSerializer serializer = new DataContractSerializer(t); StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(Key); using (IInputStream inStream = await file.OpenSequentialReadAsync()) { rr.Result = (type)serializer.ReadObject(inStream.AsStreamForRead()); } rr.Success = true; } catch (FileNotFoundException) { rr.Success = false; } return rr; }

    Ruhina Taj



    Wednesday, February 11, 2015 1:25 AM

All replies

  • Hi Ruhina,

    Please try to format your post readably: put the code in a code block, but not the text. I fixed that for you this time and moved your post to a more appropriate forum (you posted in the HTML/JavaScript forum).

    You are definitly not using await properly when loading the data and I would not expect correct results from the code you posted. LoadDataFromDataSource calls ReadContent but then doesn't wait for ReadContent's task to finish before to tries to use the result. I suspect that everything works correctly if the timing happens to work out that ReadContent has finished before LoadDataFromDataSource checks loadResult.Result and hangs if ReadContent has not finished.

    Instead, LoadDataFromDataSource should be marked async Task and should await the call to ReadContents. This way it won't continue on until the ReadContents call has finished, and by returning a Task the LoadDataFromDataSource caller can wait for LoadDataFromDataSource to finish.

    • Proposed as answer by Dave SmitsMVP Friday, February 13, 2015 12:57 PM
    Wednesday, February 11, 2015 2:03 AM
    Owner
  • Hi Rob,

    First, apologies for posting in the wrong forum and in the wrong format and thanks for fixing that.

    Also, thanks for your advice. I was concerned about the same but I dint know how to fix it. I modified the code like you advised. I will need to do heavy testing on it yet. Thanks for taking your time to help me.

            private async void Page_Loaded(object sender, RoutedEventArgs e)
            {
                try
                {
                    if ((Application.Current as App).ApplicationDataSource == null)
                    {
                        ReadResults loadResults = await ApplicationUtilities.LoadDataFromDataSource();
                    }
    
                    this.lstMatches.ItemsSource = (Application.Current as App).ApplicationDataSource.Matches;
                    this.lstTeams.ItemsSource = (Application.Current as App).ApplicationDataSource.Teams;
                }
    
                catch (Exception ex)
                {
                    string exception = ex.Message.ToString();
                    throw ex;
                }
            }
    
            public static async Task<ReadResults> LoadDataFromDataSource()
            {
                try
                {
                    UltimateCricketScorerDataSource dataSource = new UltimateCricketScorerDataSource();
                    ReadResults loadResults = await ReadContent<UltimateCricketScorerDataSource>("UltimateCricketScorer", dataSource.GetType());
    
                    if (loadResults.Result != null && loadResults.Success == true)
                    {
                        dataSource = loadResults.Result as UltimateCricketScorerDataSource;
                        (Application.Current as App).ApplicationDataSource = dataSource;
                    }
                    else if (loadResults.Result == null)
                    {
                        //File Not Found. Create it for the first time.
                        ApplicationUtilities.CreateFileOnFirstLoad();
                    }
    
                    return loadResults;
                }
                catch (Exception ex)
                {
                    string excep = ex.ToString();
                    throw;
                }
            }
    
    


    Ruhina Taj

    Thursday, February 12, 2015 5:39 PM