2

[edit] I want to clarify that the NullReferenceException does not occur within the posted code, but this code somehow gives back null

I'm getting a NullReferenceException when running my application for the first time, and it happens when I access a list as a property. Here is the code:

/// <summary>
/// Gets the list of workouts using Lazy Loading.
/// </summary>
/// <remarks>
/// This is the point of access for Workouts in this Page.
/// </remarks>
public List<WorkoutModel> Workouts
{
    get
    {
        if (workouts == null || !workouts.Any())
        {
            workouts = JsonFileHelper.LoadWorkouts();
        }

        return workouts;
    }
}

The JsonFileHelper code that is accessed is here:

/// <summary>
/// Retrieves all the workouts from local storage.
/// </summary>
/// <returns>The list of workouts.</returns>
public static List<WorkoutModel> LoadWorkouts()
{
    bool couldLoadFile = true;
    List<WorkoutModel> workouts = new List<WorkoutModel>();

    StorageFolder localFolder = ApplicationData.Current.LocalFolder;
    StorageFile textFile = null;

    Task<List<WorkoutModel>> t = Task<List<WorkoutModel>>.Run(() => LoadWorkoutsAsync(textFile, localFolder, couldLoadFile));
    t.Wait();

    workouts = t.Result;

    return workouts;
}

Which calls this method on a background thread:

private static async Task<List<WorkoutModel>> LoadWorkoutsAsync(StorageFile textFile, StorageFolder localFolder, bool couldLoadFile)
{
    List<WorkoutModel> workouts = new List<WorkoutModel>();

    if (localFolder != null)
    {
        try
        {
            textFile = await localFolder.GetFileAsync(AppResources.FileName);
        }
        catch (FileNotFoundException)
        {
            couldLoadFile = false;
        }

        if (couldLoadFile)
        {
            // Create and use a stream to the file atomically
            using (IRandomAccessStream textStream = await textFile.OpenReadAsync())
            {
                // Read the text stream atomically
                using (DataReader textReader = new DataReader(textStream))
                {
                    uint length = (uint)textStream.Size;
                    await textReader.LoadAsync(length);

                    string data = textReader.ReadString(length);

                    workouts = JsonConvert.DeserializeObject<List<WorkoutModel>>(data);
                }
            }
        }
    }

    return workouts;
}

I've noticed that when debugging, the application does not crash - this leads me to believe there is some issue with synchronization going on, because it crashes when the application is run normally. This is my first foray into to asynchronous code, so there's probably something I'm missing.

What could be causing this problem?

jschneidereit
  • 323
  • 1
  • 6
  • 2
    Almost all cases of `NullReferenceException` are the same. Please see "[What is a NullReferenceException in .NET?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net)" for some hints. – John Saunders Jan 20 '14 at 04:02

2 Answers2

0

Please read the John Saunders question. You need this knowledge, and you should have already found it before posting here.

The code needs to be restructured with variables set predictably on all paths. It's not surprising if you get errors of this kind as it is.

An exception other than FileNotFoundException will leave couldLoadFile as true and textFile as null, triggering this error. This could be your bug.

If this is not enough, then please provide the stack trace.

david.pfx
  • 10,520
  • 3
  • 30
  • 63
  • Seems to me the issue is with t.Result giving back null somehow - can't think of a case where waiting on local storage to get a file throws an exception other than FileNotFoundException. – Phillip Carter Jan 21 '14 at 18:39
0

Instead of using Task.Wait you should try Task.Result.

/// /// Retrieves all the workouts from local storage. /// /// The list of workouts.

public static List<WorkoutModel> LoadWorkouts()
{
    bool couldLoadFile = true;
    List<WorkoutModel> workouts = new List<WorkoutModel>();

    StorageFolder localFolder = ApplicationData.Current.LocalFolder;
    StorageFile textFile = null;

    List<WorkoutModel> workouts = Task<List<WorkoutModel>>.Run(() => LoadWorkoutsAsync(textFile, localFolder, couldLoadFile)).Result;

    return workouts;
}
Muhammad Umar
  • 3,761
  • 1
  • 24
  • 36