1

This might be a silly question. But when I modified one example from Live SDK example, got a weird problem.

I was thinking the root cause is async function GetAll() was used synchronously.

Below is the code snippet, I put the problem as comments. Thanks in advance!

class SkyeDriveViewModel: INotifyPropertyChanged
{
    private List<SkyDriveItem> folderList = null;
    public List<SkyDriveItem> FolderList
    {
        get { return folderList; }
        private set
        {
            if (value != folderList)
            {

                folderList = value;
                NotifyPropertyChanged("FolderList");
            }
        }
    }

    private async void GetAll(string desiredPath)
    {
        FolderList = new List<SkyDriveItem>();

        this.liveClient = new LiveConnectClient(SkyDrivePage.Session);
        try
        {
            LiveOperationResult operationResult = await this.liveClient.GetAsync(desiredPath);
            dynamic result = operationResult.Result;

            dynamic items = result.data;
            foreach (dynamic item in items)
            {
                SkyDriveItem newItem = new SkyDriveItem(item);
                if (newItem.IsFolder)
                {
                    FolderList.Add(newItem);
                }

            }

        }
        catch (LiveConnectException e)
        {
        }
        //**till here, FolderList was assigned**
    }

    public void InitList()
    {
        Debugger.Log();
        GetAll(SKYDRIVEINITPATH);
        Debugger.LogWhen(eDebugger.LogTiming.Exit); 
        //**till here, FolderList had zero item**
    }

}
tao
  • 251
  • 3
  • 13

1 Answers1

5

In general having an async void function is a warning sign. You should only have such a method for an event handler. The appropriate return type for GetAll is Task, or possibly even Task<List<SkyDriveItem>>.

The issue is that calling GetAll will only execute code until it hits the first await call, at which point it returns to the caller and the remainder of the method will be executed asynchronously.

The problem here is that because the method is void you have no way of knowing when it's done. You have a "fire and forget" method and can never know when your list is actually ready. If GetAll returns a task then you can await that task and be sure that your list has actually been populated.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • +1. `GatAll` should return `Task` and than you can call `Wait` on result if calling function *must* by synchronous. – Alexei Levenkov May 16 '13 at 20:25
  • @AlexeiLevenkov If the caller needs it to be synchronous then the method probably shouldn't be asynchronous at all to begin with... – Servy May 16 '13 at 20:26
  • I found a solution from here[link](http://stackoverflow.com/questions/5095183/how-would-i-run-an-async-taskt-method-synchronously). So the **public static void RunSync(Func task)** seems to be the solution. – tao May 16 '13 at 20:44
  • @tao Even that won't help you if you don't convert the function into one that returns a `Task` instead of `void`. – Servy May 16 '13 at 20:54
  • @Servy You are absolutely right about `asyn void` and `await`. I tried to use event handler, it started working. Thanks again! – tao May 17 '13 at 05:29