我今天一直在尝试使用WP7应用程序并且已经打了一针墙。 我喜欢在用户界面和主应用程序代码之间进行分离,但是我已经碰壁了。
我已经成功实现了webclient请求并获得了结果,但由于调用是异步的,我不知道如何将此备份传递到UI级别。我似乎无法等待对完成或任何事情的回应。 我一定是做错了。
(这是我在我的网站上下载的xbox360Voice库:http://www.jamesstuddart.co.uk/Projects/ASP.Net/Xbox_Feeds/我将其作为测试移植到WP7上)
这是后端代码片段:
internal const string BaseUrlFormat = "http://www.360voice.com/api/gamertag-profile.asp?tag={0}";
internal static string ResponseXml { get; set; }
internal static WebClient Client = new WebClient();
public static XboxGamer? GetGamer(string gamerTag)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null);
return SerializeResponse(response);
}
internal static XboxGamer? SerializeResponse(string response)
{
if (string.IsNullOrEmpty(response))
{
return null;
}
var tempGamer = new XboxGamer();
var gamer = (XboxGamer)SerializationMethods.Deserialize(tempGamer, response);
return gamer;
}
internal static string GetResponse(string url, string userName, string password)
{
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
Client.Credentials = new NetworkCredential(userName, password);
}
try
{
Client.DownloadStringCompleted += ClientDownloadStringCompleted;
Client.DownloadStringAsync(new Uri(url));
return ResponseXml;
}
catch (Exception ex)
{
return null;
}
}
internal static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
ResponseXml = e.Result;
}
}
这是前端代码:
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
var xboxGamer = xboxManager.GetGamer();
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
现在我明白我需要在ClientDownloadStringCompleted
中放置一些东西,但我不确定是什么。
答案 0 :(得分:6)
您遇到的问题是,只要在代码路径中引入异步操作,整个代码路径就需要变为异步。
GetResponse
调用DownloadStringAsync
它必须变为异步,它不能返回字符串,它只能在回调中执行此操作GetGamer
调用现在异步的GetResponse
,因此无法返回XboxGamer
,它只能在回调中执行此操作GetGamerDetails
调用GetGamer
现在是异步的,因此无法在调用后继续使用其代码,只有在收到来自GetGamer
的回调后才能执行此操作。 GetGamerDetails
现在是异步的,所以调用它也必须承认这种行为。这是一些空气代码,它会在代码中产生一些异步性。
public static void GetGamer(string gamerTag, Action<XboxGamer?> completed)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null, (response) =>
{
completed(SerializeResponse(response));
});
}
internal static string GetResponse(string url, string userName, string password, Action<string> completed)
{
WebClient client = new WebClient();
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
client.Credentials = new NetworkCredential(userName, password);
}
try
{
client.DownloadStringCompleted += (s, args) =>
{
// Messy error handling needed here, out of scope
completed(args.Result);
};
client.DownloadStringAsync(new Uri(url));
}
catch
{
completed(null);
}
}
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
xboxManager.GetGamer( (xboxGamer) =>
{
// Need to move to the main UI thread.
Dispatcher.BeginInvoke(new Action<XboxGamer?>(DisplayGamerDetails), xboxGamer);
});
}
void DisplayGamerDetails(XboxGamer? xboxGamer)
{
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
正如您所看到的,异步编程可能会变得非常混乱。
答案 1 :(得分:2)
您通常有2个选项。要么将后端代码公开为异步API,要么等待GetResponse中的调用完成。
以异步方式执行此操作意味着将进程放在一个位置,然后返回,并在数据可用时进行UI更新。这通常是首选方法,因为只要方法正在运行,在UI线程上调用阻塞方法就会使您的应用程序看起来没有响应。
答案 2 :(得分:1)
我认为“Silverlight Way”将使用databinding。您的XboxGamer对象应该实现INotifyPropertyChanged接口。当你调用GetGamer()时,它会立即返回一个“空”的XboxGamer对象(可能是GamerTag ==“正在加载......”或其他东西)。在ClientDownloadStringCompleted处理程序中,您应该反序列化返回的XML,然后触发INotifyPropertyChanged.PropertyChanged事件。
如果您查看SDK中的“Windows Phone数据绑定应用程序”项目模板,则以这种方式实现ItemViewModel类。
答案 3 :(得分:0)
Here是如何向WP7上的任何类型公开异步功能的。