在Windows Phone应用程序中,从DownloadStringCompleted处理器中填充并返回实体
本文关键字:填充 处理器 实体 返回 DownloadStringCompleted Windows Phone 应用程序 | 更新日期: 2023-09-27 17:52:57
我有一个从url获取HTML的方法,通过解析它提取实体,并返回实体列表。下面是示例代码:
public List<Entity> FetchEntities()
{
List<Entity> myList = new List<Entity>();
string url = "<myUrl>";
string response = String.Empty;
client = new WebClient();
client.DownloadStringCompleted += (sender, e) =>
{
response = e.Result;
// parse response
// extract content and generate entities
// <---- I am currently filling list here
};
client.DownloadStringAsync(new Uri(url));
return myList;
}
问题是,当异步调用正在进行时,控制返回空myList
。我该如何预防呢?我的最终目标是返回填充的列表。
而且这个方法在一个单独的类库项目中并且从windows phone应用程序中被调用我必须保持它只是那样。有什么办法做到这一点,还是我错过了什么?
您可以像这样传递回调给方法并使其不带任务而异步,因此您必须稍微更新方法用法。
public void FetchEntities(
Action<List<Entity>> resultCallback,
Action<string> errorCallback)
{
List<Entity> myList = new List<Entity>();
string url = "<myUrl>";
string response = String.Empty;
client = new WebClient();
client.DownloadStringCompleted += (sender, e) =>
{
response = e.Result;
// parse response
// extract content and generate entities
// <---- I am currently filling list here
if (response == null)
{
if (errorCallback != null)
errorCallback("Ooops, something bad happened");
}
else
{
if (callback != null)
callback(myList);
}
};
client.DownloadStringAsync(new Uri(url));
}
另一个选项是强制它是同步的。这样的
public List<Entity> FetchEntities()
{
List<Entity> myList = new List<Entity>();
string url = "<myUrl>";
string response = String.Empty;
client = new WebClient();
AutoResetEvent waitHandle = new AutoResetEvent(false);
client.DownloadStringCompleted += (sender, e) =>
{
response = e.Result;
// parse response
// extract content and generate entities
// <---- I am currently filling list here
waitHandle.Set();
};
client.DownloadStringAsync(new Uri(url));
waitHandle.WaitOne();
return myList;
}
这就是异步编程非阻塞的要点。你可以将回调作为参数传递,并在其他地方处理结果,而不是尝试返回它。
如果你需要返回结果,你可以使用这个TPL库,我已经使用它没有问题一段时间了。
public Task<string> GetWebResultAsync(string url)
{
var tcs = new TaskCompletionSource<string>();
var client = new WebClient();
DownloadStringCompletedEventHandler h = null;
h = (sender, args) =>
{
if (args.Cancelled)
{
tcs.SetCanceled();
}
else if (args.Error != null)
{
tcs.SetException(args.Error);
}
else
{
tcs.SetResult(args.Result);
}
client.DownloadStringCompleted -= h;
};
client.DownloadStringCompleted += h;
client.DownloadStringAsync(new Uri(url));
return tcs.Task;
}
}
调用它正是你在。net 4.0中使用TPL的方式
GetWebResultAsnyc(url).ContinueWith((t) =>
{
t.Result //this is the downloaded string
});
或:
var downloadTask = GetWebResultAsync(url);
downloadTask.Wait();
var result = downloadTask.Result; //this is the downloaded string
希望这对你有帮助