Search code examples
c#windows-store-appsasync-awaitmonogamelive-connect-sdk

why does async call LiveConnectClient.GetAsync block executing thread?


I have Windows Store MonoGame (based on XAML MonoGame template in Visual Studio 2012) app.
When I connect to LiveConnect, system does all things in background, but when I call LiveConnectClient.GetAsync to get user info it sometimes (and usually) blocks the caller thread, even though it is called using await. Is there any way to make GetAsync call really async? Maybe I should create a new thread to call it?

Here's the caller code. It is called inside MonoGame draw thread (can't access main UI thread in MonoGame).

private static LiveConnectSession session = null;
private static LiveAuthClient liveAuthClient = null;
private static LiveConnectClient liveConnectClient = null;

public static async Task AuthAsync()
{
    liveAuthClient = new LiveAuthClient();
    LiveLoginResult liveLoginResult = await liveAuthClient.InitializeAsync();
    liveLoginResult = await liveAuthClient.LoginAsync(new List<string> { "wl.signin" });
    if (liveLoginResult.Status == LiveConnectSessionStatus.Connected)
    {
        session = liveLoginResult.Session;
        liveConnectClient = new LiveConnectClient(session);
        LiveOperationResult liveOperationResult = await liveConnectClient.GetAsync("me");
        dynamic meResult = liveOperationResult.Result;
        MyEngine.userID = meResult.id;
    }
}

Solution

  • Thanks to Nate Diamond, I've found a workaround (or maybe it's the only solution). The trick is to await intialization and connect in main thread (in windows store app it's not the ui thread, but somehow it's the main one), then create thread and await GetAsync in it. For the sake of clarity I've skipped all try..catch..finally and everything unnecessary. Now it let draw thread work w/o freezes. Here' the code:

    private static LiveConnectSession session = null;
    private static LiveAuthClient liveAuthClient = null;
    private static LiveConnectClient liveConnectClient = null;
    
    public static async Task AuthAsync()
    {
        await AuthAsyncInternal();
        if (liveConnectClient != null)
        {
            await Task.Run(async () =>
                {
                    LiveOperationResult liveOperationResult = 
                        await liveConnectClient.("me");
                    dynamic meResult = liveOperationResult.Result;
                    MyEngine.userID = meResult.id;
                });
        }
    }
    
    private static async Task AuthAsyncInternal()
    {
        liveAuthClient = new LiveAuthClient();
        LiveLoginResult liveLoginResult = await liveAuthClient.InitializeAsync();
        liveLoginResult = await liveAuthClient.LoginAsync(new List<string> { "wl.signin" });
        if (liveLoginResult.Status == LiveConnectSessionStatus.Connected)
        {
            session = liveLoginResult.Session;
            liveConnectClient = new LiveConnectClient(session);
        }
    }
    

    And here's variant for Windows Phone 8:

    private static async Task AuthAsyncInternal()
    {
        Deployment.Current.Dispatcher.BeginInvoke(async delegate()
            {
                liveAuthClient = new LiveAuthClient("your client id here");
                LiveLoginResult liveLoginResult = await liveAuthClient.InitializeAsync();
                liveLoginResult = await liveAuthClient.LoginAsync(new List<string> { "wl.signin" });
                if (liveLoginResult.Status == LiveConnectSessionStatus.Connected)
                {
                    session = liveLoginResult.Session;
                    liveConnectClient = new LiveConnectClient(session);
                    await Task.Run(async () =>
                        {
                            LiveOperationResult liveOperationResult = 
                                await liveConnectClient.("me");
                            dynamic meResult = liveOperationResult.Result;
                            MyEngine.userID = meResult.id;
                        });
                }
            });
    }