问题
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;
}
}
回答1:
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;
});
}
});
}
回答2:
Bit off topic (not about threading) but maybe helpful to someone.
I've found that a call to LiveAuthClient's LoginAsync() was taking up to 12 seconds, and usually around 7-8 secs (in a win 8.1 store app in c# & XAML)
e.g.
LiveAuthClient auth = new LiveAuthClient(_redirectDomain);
_loginResult = await auth.LoginAsync(new string[] { "wl.signin", "wl.basic", "wl.emails" });
Found that once I closed Fiddler (an http proxy/inspector) this dropped to a much more reasonable ~2 seconds
This is still pretty slow and lame (no idea why its so slow - note : I think upgrading from 5.5 to 5.6 slowed it down) but obviously much better.
Might help someone.
来源:https://stackoverflow.com/questions/22304260/why-does-async-call-liveconnectclient-getasync-block-executing-thread