我有一个标题列表,我试图通过使用更新标题对象参数的任务来处理。我尝试使用的代码实际上并没有正确填充参数。当我调试它时,我可以看到正在激活setter并正确更新支持字段,但是在Task.WhenAll之后检查时,实际上没有任何属性设置为它们的预期值。
//**Relevant signatures are:**
class Headline{
public Uri Uri { get; set; }
public IEnumerable<string> AttachedEmails { get; set; } = Enumerable.Empty<string>();
}
async Task<IEnumerable<string>> GetEmailsFromHeadline(Uri headlineUri) {
//bunch of async fetching logic that populates emailNodes correctly
return emailNodes.Select(e => e.InnerText).ToList();
}
//**Problem Area**
//Initiate tasks that start fetching information
var taskList =
postData
.Select(e => new HttpRequest() { Uri = actionUri, PostData = e })
.Select(e => Task.Run(() => GetHeadlines(e)))
.ToList();
//Wait till complete
await Task.WhenAll(taskList);
//Flatten list
var allHeadlines =
taskList
.SelectMany(e => e.Result.ToList());
//After this section of code I expect every member AttachedEmails property to be properly updated but this is not what is happening.
var headlineProcessTaskList =
allHeadlines
.Select(e => Task.Run( new Func<Task>( async () => e.AttachedEmails = await GetEmailsFromHeadline(e.Uri) ) ) )
.ToList();
await Task.WhenAll(headlineProcessTaskList);
答案 0 :(得分:2)
没有足够的代码来重现问题。但是,我们可以猜到:
allHeadlines is IEnumerable<Headline>
由于这是IEnumerable<T>
,可能它是一个已被延迟的LINQ查询。因此,当您在ToList
调用中枚举一次时,会创建设置了Headline
的{{1}}个实例。但是当您稍后再次枚举 时,它会创建新的AttachedEmails
个实例。
如果这是正确的,那么一种解决方案是将Headline
的类型更改为allHeadlines
。
类似的问题可能发生在List<Headline>
,可能会返回GetEmailsFromHeadline
而不是Task<IEnumerable<string>>
。如果枚举是延迟的,则唯一的异步部分是定义查询; 执行它将在事后 - 更具体地说,在IEnumerable<string>
之外。您可能也想考虑在那里使用Task.Run
。
另一方面,ToList
只是噪音,new Func
中异步任务的包装非常不寻常。这将更加惯用:
Task.Run
或者,如果确实需要 var headlineProcessTaskList =
allHeadlines
.Select(async e => e.AttachedEmails = await GetEmailsFromHeadline(e.Uri) )
.ToList();
:
Task.Run