等到异步操作结束Windows Phone

时间:2014-06-05 08:01:45

标签: windows-phone-8 asynchronous

我正在尝试从服务器的xml下载中解析一些poi,我看到它是在程序继续在主线程中完成的。我找不到解决方法,因为我需要它。

using System.Threading;

namespace XML_Parser
{
    class XMLParserPOI_Wiki
    {
        private static XMLParserPOI_Wiki objSingle = new XMLParserPOI_Wiki();
        public static XMLParserPOI_Wiki ObjSingle
        {
            get { return objSingle; }
            set { objSingle = value; }
        }
        private List<POI> places;
        public List<POI> Places
        {
            get { return places; }
        }
        private XMLParserPOI_Wiki()
        {

        }



        public void parseWikitude(string url)
        {
            places = new List<POI>();
            WebClient wc = new WebClient();
            wc.DownloadStringCompleted += HttpsCompleted;
            wc.DownloadStringAsync(new Uri(url));            
        }

        private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                XDocument xdoc = XDocument.Parse(e.Result, LoadOptions.None);
                XNamespace ns = "http://www.opengis.net/kml/2.2";
                XNamespace ns2 = "http://www.openarml.org/wikitude/1.0";
                var placemarkers = xdoc.Root.Descendants(ns + "Placemark");
                places =
                (from query in xdoc.Root.Descendants(ns + "Placemark")
                 select new POI
                 (
                   ...
                 )).ToList();
                System.Diagnostics.Debug.WriteLine("Lista");
                System.Diagnostics.Debug.WriteLine(places.Count);

            }
        }

    }
}

在我的主要课程中:

XMLParserPOI_Wiki parserXML = XMLParserPOI_Wiki.ObjSingle;

        parserXML.parseWikitude("http://myurl.php");
        System.Diagnostics.Debug.WriteLine("Lista de pois");
        System.Diagnostics.Debug.WriteLine(parserXML.Places.Count);
        for (int i = 0; i < parserXML.Places.Count; i++)
        {
            System.Diagnostics.Debug.WriteLine(parserXML.Places[i].getName());
        }

在Lista和X(pois的数量)之前打印Lista de POis和0

我想我应该冻结主线程,但我尝试了几次示例并且它们没有用。

你能指点我这方面的任何教程吗?除了得到答案,我想了解如何处理这种操作

1 个答案:

答案 0 :(得分:2)

首先,您不想阻止(冻结)UI线程EVER!

这称为异步编程。你可以做两件事来解决问题(我推荐选项2!):

  1. 使用经典回调模型。你基本上在后台线程上调用一些长操作并给它一个函数,在长操作完成时执行。以下是如何在您的情况下执行此操作。

    HttpsCompleted方法结束时,使用以下方法在UI线程上调用所需内容:

    Deployment.Current.Dispatcher.BeginInvoke(delegate() {
        //The code here will be invoked on the UI thread
    });
    

    如果要使parseWikitude方法可重用,则应将Action传递给它。这样,您可以从多个位置调用它,并在解析完成时告诉它在UI线程上要做什么。像这样:

    public void parseWikitude(string url, Action callback) {
        places = new List<POI>();
        WebClient wc = new WebClient();
        wc.DownloadStringCompleted += HttpsCompleted;
        wc.DownloadStringAsync(new Uri(url), callback);
    }
    
    private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            ...
    
            var callback = (Action)e.UserState;
            Deployment.Current.Dispatcher.BeginInvoke(callback);
        }
    }
    
    //And then when you use it, you do it like that
    parserXML.parseWikitude("http://myurl.php", delegate() {
       //The code here will be executed on the UI thread, after the parsing is done 
    });
    
  2. 在.NET中使用(相当)新的asnyc模式。你应该读一下这个,因为如果你问我这是.NET最好的功能之一。 :)它基本上自动执行回调操作,使代码更容易阅读/维护/工作。一旦你习惯了,那就是。

    以下是一个例子:

    public Task<List<POI>> parseWikitude(string url) {
        TaskCompletionSource<List<POI>> resultTaskSource = new TaskCompletionSource<List<POI>>();
    
        WebClient wc = new WebClient();
        wc.DownloadStringCompleted += HttpsCompleted;
        wc.DownloadStringAsync(new Uri(url), resultTaskSource);
    
        return resultTaskSource.Task;
    }
    
    private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            //If needed, run the code here in a background thread
            //...
    
            var resultTaskSource = (TaskCompletionSource<List<POI>>)e.UserState;
            resultTaskSource.SetResult(places);
        }
    }
    
    //And when you need to use it, do it like that (note, this must be invoked in an async method!)
    var places = await parser.parseWikitude("http://myurl.php");
    //The code here will be executed on the same thread when the parsing is done, but the thread will not be blocked while the download is happening.
    
  3. 所以,这些是你可以处理它的两种方式。选项一是老派,经典而且容易。选项二是执行异步内容的新方法。这真的是必须知道的。一旦你习惯它就会简化很多事情。

    P.S。对不起,如果我被带走了。 :d