gpt4 book ai didi

c# - Task.WaitAll 不等待其他异步方法

转载 作者:行者123 更新时间:2023-11-30 14:33:21 26 4
gpt4 key购买 nike

我正在使用我的可移植类库异步检索一些 rss 文章,该类库使用 Microsoft.Bcl 库(没有 Task.WhenAll)。每篇文章都有一个 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;
}

解决方案中的更新代码,刚刚在 Enqueue 方法上添加了 .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());

最佳答案

它正在适本地等待。问题是您正在创建一个 Task这会创建另一个任务(即 StartNew 正在返回一个 Task<Task> 而您只在等待外部 Task 完成得相当快(它在内部任务完成之前完成))。

问题将是:

  • 你真的想要那个内心的任务吗?
    • 如果是,那么您可以使用 Task.Unwrap得到一个代表内部和外部都完成的代理任务Task并用它来等待。
    • 如果不是,那么您可以删除 async 的使用/await在 StartNew 中,这样就没有内部任务(我认为这是首选,目前尚不清楚为什么需要内部任务)。
  • 你真的需要同步 Wait在异步任务上?阅读 Stephen Cleary 的一些博客:http://blog.stephencleary.com/2012/02/async-unit-tests-part-1-wrong-way.html

顺便说一句,如果您不使用 C# 5,请注意关闭 foreach 变量 result

关于c# - Task.WaitAll 不等待其他异步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16675288/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com