3

Microsoft.Bcl ライブラリ (Task.WhenAll を持たない) を使用するポータブル クラス ライブラリを使用して、いくつかの RSS 記事を非同期的に取得しています。各記事には、RSS コメントへの URL があり、これも非同期で取得する必要があります。

以下のコードは私のライブラリです。GetArticles() を呼び出しますが、非同期でコメントを取得するために GetComments() を呼び出すタスクのリストを作成するいずれも返されません。

GetArticles で Task.WaitAll を使用してコメントを待機しようとしましたが、スレッドをブロックしません。どんな助けでも大歓迎です。

    private const string ArticlesUri = "";

    public async Task<List<ArticleBrief>> GetArticles()
    {
        var results = new List<ArticleBrief>();
        try
        {
            var wfw = XNamespace.Get("http://wellformedweb.org/CommentAPI/");
            var media = XNamespace.Get("http://search.yahoo.com/mrss/");
            var dc = XNamespace.Get("http://purl.org/dc/elements/1.1/");

            var t = await WebHttpRequestAsync(ArticlesUri);
            StringReader stringReader = new StringReader(t);
            using (var xmlReader = System.Xml.XmlReader.Create(stringReader))
            {
                var doc = System.Xml.Linq.XDocument.Load(xmlReader);
                results = (from e in doc.Element("rss").Element("channel").Elements("item")
                           select
                               new ArticleBrief()
                               {
                                   Title = e.Element("title").Value,
                                   Description = e.Element("description").Value,
                                   Published = Convert.ToDateTime(e.Element("pubDate").Value),
                                   Url = e.Element("link").Value,
                                   CommentUri = e.Element(wfw + "commentRss").Value,
                                   ThumbnailUri = e.Element(media + "thumbnail").FirstAttribute.Value,
                                   Categories = GetCategoryElements(e.Elements("category")),
                                   Creator = e.Element(dc + "creator").Value
                               }).ToList();

            }

            var tasks = new Queue<Task>();
            foreach (var result in results)
            {
                tasks.Enqueue(
                    Task.Factory.StartNew(async ()=>
                        {
                            result.Comments = await GetComments(result.CommentUri);
                        }
                    ));
            }

            Task.WaitAll(tasks.ToArray());
        }
        catch (Exception ex)
        {
            // should do some other
            // logging here. for now pass off
            // exception to callback on UI
            throw ex;
        }

        return results;
    }

    public async Task<List<Comment>> GetComments(string uri)
    {
        var results = new List<Comment>();
        try
        {
            var wfw = XNamespace.Get("http://wellformedweb.org/CommentAPI/");
            var media = XNamespace.Get("http://search.yahoo.com/mrss/");
            var dc = XNamespace.Get("http://purl.org/dc/elements/1.1/");

            var t = await WebHttpRequestAsync(uri);
            StringReader stringReader = new StringReader(t);
            using (var xmlReader = System.Xml.XmlReader.Create(stringReader))
            {
                var doc = System.Xml.Linq.XDocument.Load(xmlReader);
                results = (from e in doc.Element("rss").Element("channel").Elements("item")
                           select
                               new Comment()
                               {
                                   Description = e.Element("description").Value,
                                   Published = Convert.ToDateTime(e.Element("pubDate").Value),
                                   Url = e.Element("link").Value,
                                   Creator = e.Element(dc + "creator").Value
                               }).ToList();
            }
        }
        catch (Exception ex)
        {
            // should do some other
            // logging here. for now pass off
            // exception to callback on UI
            throw ex;
        }

        return results;
    }

    private static async Task<string> WebHttpRequestAsync(string url)
    {
        //TODO: look into getting 
        var request = WebRequest.Create(url);
        request.Method = "GET";

        var response = await request.GetResponseAsync();
        return ReadStreamFromResponse(response);
    }

    private static string ReadStreamFromResponse(WebResponse response)
    {
        using (Stream responseStream = response.GetResponseStream())
        using (StreamReader sr = new StreamReader(responseStream))
        {
            string strContent = sr.ReadToEnd();
            return strContent;
        }
    }

    private List<string> GetCategoryElements(IEnumerable<XElement> categories)
    {
        var listOfCategories = new List<string>();

        foreach (var category in categories)
        {
            listOfCategories.Add(category.Value);
        }

        return listOfCategories;
    }

ソリューションからコードを更新し、エンキュー メソッドに .UnWrap() を追加しました。

            var tasks = new Queue<Task>();
            foreach (var result in results)
            {
                tasks.Enqueue(
                    Task.Factory.StartNew(async ()=>
                        {
                            result.Comments = await GetComments(result.CommentUri);
                        }
                    ).Unwrap());
            }

            Task.WaitAll(tasks.ToArray());
4

2 に答える 2

2

ではMicrosoft.Bcl.Async、Task に静的メソッドを追加できませんでした。ただし、TaskExたとえば、ほとんどのメソッドTaskEx.WhenAll()は存在します。

于 2013-05-23T17:01:13.753 に答える