0

While on my local box the following code works:

 public async Task<GameStatistic> LoadReport()
    {
        var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(FolderName, CreationCollisionOption.OpenIfExists);
        var file = await folder.GetFileAsync(FileName);

        GameStatistic returnValue;
        using (var inStream = await file.OpenSequentialReadAsync())
        {
            var serializer = new DataContractJsonSerializer(typeof (GameStatistic));
            returnValue = serializer.ReadObject(inStream.AsStreamForRead()) as GameStatistic;
        }
        return returnValue;
    }

Code that calls the above method:

  public GameStatistic GetReportData()
    {
        var repo = new GameRepository();
        var gameStatTask = repo.LoadReport(); //(awaitable) Task<GameStatistic>

        gameStatTask.Wait();  //this seems to make no difference
        return gameStatTask.Result;
    }

But When I move to code to my Surface Pro and run the application (no debugger), the folder.GetFileAsync(FileName) fails because the async call to get the folder hasn't returned yet.

When I debug the application on my Surface Pro (via Remote Machine) and slowly walk the debugger past the first line of code and wait a few seconds, and then step again, everything works.

I don't like the idea of trying to put a thread to sleep for an arbitrary length of time, but I am not sure what else I can do here.

Is there something I am doing wrong or something I should be doing that I am not doing at all? Is there a common practice that would really wait until the CreateFolderAsync returns so that when I call folder.GetFileAsync that I could be sure the preceding line was complete?

Thanks for any help you may be able to provide.

N_A
  • 19,799
  • 4
  • 52
  • 98
LWarthen
  • 109
  • 2
  • 7
  • check out this SO thread http://stackoverflow.com/questions/13140523/await-vs-task-wait-deadlock (or more specifically its answer). I'm not sure, but I think that your might need to use `await gameStatTask` instead of `.Wait()`? – J.B Apr 28 '13 at 17:00
  • Thanks for the input. Unfortunately there was no change. The code that is the problem already has the await keyword, but the next line executes even though the task isn't complete. – LWarthen Apr 28 '13 at 18:08

1 Answers1

0

As @J.B points out you need to use await instead of wait. Also, any function that calls an async method should itself be async (there is at least one exception to this). So almost your entire call stack up to the UI must be changed to be some variation of async Task<...>...:

async public Task<GameStatistic> GetReportData()
{
    var repo = new GameRepository();
    return await repo.LoadReport(); //(awaitable) Task<GameStatistic>
}

Caller of above (just an arbitrary method):

async public Task<MyResultClass> GetReportAndResult()
{
     var gameStat = await GetReportData();
     return ReportDataToMyResult(gameStat);
}

Top of call chain (event handler) must be async void:

async void GetReportData_ButtonClick(...)
{
    var result = await GetReportAndResult();
    // do something with result
    // ...
}
chue x
  • 18,573
  • 7
  • 56
  • 70
  • Thanks for you input. I may need to clarify a bit more. I am using MVVM pattern and my ReportViewModel's constructor is calling the GetReportData() so my top of the call chain is a constructor. Basically I wanted to have the report loaded by the time the xaml view was displayed. Is it not possible to do what I want in the constructor? – LWarthen Apr 28 '13 at 19:05
  • @LanceWarthen - unfortunately `async` and constructors don't mix. One approach is to have an additional `async` method that does the intitialization. – chue x Apr 28 '13 at 19:42
  • I have simplified it as much as possible. I created a button_click event and load the data once the button is pushed. Not what I really wanted, but such is life... It would have been nice to have the frame loaded via instantiation rather than on user interaction. But it works. Thank you very much @Chue x – LWarthen Apr 28 '13 at 20:54