我正在从webs下载两个JSON文件,之后我希望允许加载两个页面,但不允许在之前加载。但是,为了加载页面而需要设置的ManualResetEvent永远不会“触发”。即使我知道它已经设置好了,WaitOne也再也不会回来了。
方法启动下载:
private void Application_Launching(object sender, LaunchingEventArgs e)
{
PhoneApplicationService.Current.State["doneList"] = new List<int>();
PhoneApplicationService.Current.State["manualResetEvent"] = new ManualResetEvent(false);
Helpers.DownloadAndStoreJsonObject<ArticleList>("http://arkad.tlth.se/api/get_posts/", "articleList");
Helpers.DownloadAndStoreJsonObject<CompanyList>("http://arkad.tlth.se/api/get_posts/?postType=webbkatalog", "catalog");
}下载方法,它设置ManualResetEvent
public static void DownloadAndStoreJsonObject<T>(string url, string objName)
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += (sender, e) =>
{
if (!string.IsNullOrEmpty(e.Result))
{
var obj = ProcessJson<T>(e.Result);
PhoneApplicationService.Current.State[objName] = obj;
var doneList = PhoneApplicationService.Current.State["doneList"] as List<int>;
doneList.Add(0);
if (doneList.Count == 2) // Two items loaded
{
(PhoneApplicationService.Current.State["manualResetEvent"] as ManualResetEvent).Set(); // Signal that it's done
}
}
};
webClient.DownloadStringAsync(new Uri(url));
}等待方法(在本例中为构造函数)
public SenastePage()
{
InitializeComponent();
if ((PhoneApplicationService.Current.State["doneList"] as List<int>).Count < 2)
{
(PhoneApplicationService.Current.State["manualResetEvent"] as ManualResetEvent).WaitOne();
}
SenasteArticleList.ItemsSource = (PhoneApplicationService.Current.State["articleList"] as ArticleList).posts;
}如果我在尝试访问构造函数之前等待,它很容易地传递If语句,并且不会被WaitOne捕获,但是如果我立即调用它,我就会被卡住,它永远不会返回.
有什么想法吗?
发布于 2013-10-20 19:07:46
必须不惜一切代价防止阻塞UI线程。特别是在下载数据时:不要忘记您的应用程序是在电话上执行的,它有一个非常不稳定的网络。如果数据需要两分钟才能加载,那么UI将被冻结两分钟。这将是一个糟糕的用户体验。
有很多方法可以防止这种情况发生。例如,您可以保持相同的逻辑,但在后台线程中等待,而不是在UI线程中等待:
public SenastePage()
{
// Write the XAML of your page to display the loading animation per default
InitializeComponent();
Task.Factory.StartNew(LoadData);
}
private void LoadData()
{
((ManualResetEvent)PhoneApplicationService.Current.State["manualResetEvent"]).WaitOne();
Dispatcher.BeginInvoke(() =>
{
SenasteArticleList.ItemsSource = ((ArticleList)PhoneApplicationService.Current.State["articleList"]).posts;
// Hide the loading animation
}
}这只是一种快速而肮脏的方式来达到你想要的结果。您还可以使用任务重写代码,并在任务全部完成后使用Task.WhenAll触发操作。
发布于 2013-10-20 18:51:16
也许有一个逻辑问题。在SenastePage()构造函数中,只有当doneList计数小于2时,才会等待set事件。但是,在doneList计数等于2之前,不会触发set事件。在设置事件发生之前,您正在监听它。
https://stackoverflow.com/questions/19481242
复制相似问题