我有一个列表lstSubscriptionRequests,其中我正在异步处理某些异步项目。然后在处理完所有项目之后,我必须返回更新的列表项目。我目前的实现就像
List<SubscriptionRequest> lstSubscriptionRequests = FromSomeResource();
var tsk = new List<Task>();
foreach (var oTsk in lstSubscriptionRequests.Select(objSubscriptionRequest => new Task(
() => ProcessSubscriptionForASingleRecord(objSubscriptionRequest))))
{
oTsk.Start();
lock (tsk)
{
tsk.Add(oTsk);
}
}
Task.WaitAll(tsk.ToArray());
在完成所有任务后,某些项目看起来没有更新。 请让我知道我需要的更正
答案 0 :(得分:2)
你可以更轻松地完成这项工作。请注意,通常不需要或不建议使用Task构造函数,也可能难以跟踪或调试特定对象的状态。返回表示所需状态的新对象将允许您强制执行最小有效状态。以下代码将处理您的所有项目,并将完成的项目返回到您的客户端代码。
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Processing {
public class MyProcessor {
public async Task<IEnumerable<Subscription>> ProcessSubscriptionRequestsAsync(IEnumerable<SubscriptionRequest> subscriptionRequests) {
var subscriptionProcessingTasks = subscriptionRequests.Select(request => ProcessSubscriptionForASingleRecord(request)).ToArray();
return await Task.WhenAll(subscriptionProcessingTasks);
}
public async Task<Subscription> ProcessSubscriptionForASingleRecord(SubscriptionRequest request) {
//process the request
try {
var subscription = await Context.ProcessRequest(request);
return subscription;
} catch {
//something went wrong with the request
}
}
}
public class SubscriptionRequest {
//A subcription request
}
public class Subscription {
//A completed subscription request
}
}
<强>更新强>
如果您可以排除新的类订阅并在答案中添加解决方案,这可能有所帮助。我会试一试
希望简化的前后视图将更容易集成。主要区别在于将Parallel.ForEach
替换为Select
以创建您的任务集合,而无需锁定每个SubscriptionRequest
的任务列表,同时还假设Task
并行通常不是必需的,因为每个都将异步执行,您只能获得所有等待的点,而不是完成。接下来,允许每个任务开始,并在await Task.WhenAll(tasks)
等待所有任务。确定每个SubscriptionRequest
经历的处理类型非常重要。为了举例,我假设每个请求都以某种方式链接到数据库访问,即存储请求,更新各种类型的用户配置文件等。
public class OriginalSynchronous {
public void ProcessSubscriptionRequest() {
List<SubscriptionRequest> lstSubscriptionRequests = FromSomeResource();
List<Task> tsk = new List<Task>();
Parallel.ForEach(lstSubscriptionRequests, objSubscriptionRequest => {
var oTsk =
new Task(
() => ProcessSubscriptionForASingleRecord(objSubscriptionRequest));// update some properties after processing SubscriptionRequest
oTsk.Start();
lock (tsk) {
tsk.Add(oTsk);
}
});
Task.WaitAll(tsk.ToArray());
}
private void ProcessSubscriptionForASingleRecord(SubscriptionRequest request) {
//modify SubscriptionRequest
}
}
public class ModifiedAsync {
public async Task ProcessSubscriptionRequest() {
var subscriptionRequests = await FromSomeResourceAsync();
var tasks = subscriptionRequests.Select(request => {
return ProcessSubscriptionForASingleRecord(request);
}).ToArray();
await Task.WhenAll(tasks);
}
public async Task ProcessSubscriptionForASingleRecord(SubscriptionRequest request) {
//modify SubscriptionRequest
}
}