C# 按完成顺序排列任务后,是否获取对原始任务的引用?
我不久前询问过一种方法,该方法通过完成排序C# 按完成顺序排列任务后,是否获取对原始任务的引用?,c#,exception-handling,task-parallel-library,task,C#,Exception Handling,Task Parallel Library,Task,我不久前询问过一种方法,该方法通过完成排序列表>,该方法还返回一个int,表示原始列表中已完成任务的索引 我知道我可能不需要返回此int来确定哪个特定的任务已完成,我可以询问返回的任务以获取此信息 作为旁注,我后来更改了方法,以订购列表。我最初使用的是Task,它返回一个bool来表示任务是否成功完成其工作。我现在只抛出一个子类Exception,它提供了有关任务失败的方式和原因的更多信息 我对这个问题的想法来源于这样一个问题,即当来自此方法的任务抛出异常时,我无法确定哪个特定的任务抛出了异常
列表>
,该方法还返回一个int
,表示原始列表中已完成任务的索引
我知道我可能不需要返回此int
来确定哪个特定的任务
已完成,我可以询问返回的任务
以获取此信息
作为旁注,我后来更改了方法,以订购列表
。我最初使用的是Task
,它返回一个bool
来表示任务是否成功完成其工作。我现在只抛出一个子类Exception
,它提供了有关任务失败的方式和原因的更多信息
我对这个问题的想法来源于这样一个问题,即当来自此方法的任务
抛出异常
时,我无法确定哪个特定的任务
抛出了异常
,因为我无法查询任务。对于任务
的原始索引,结果
同样,如果我可以查询从原始列表中引用的任务
(现在只需任务
)返回的任务,我可以简单地比较引用
这是目前存在的方法(此方法的成功归功于Servy,也可能来自Jon Skeet)
只要看看任何
通过其类似操作解决此问题的方式即可。让方法返回一个任务
,其结果是逻辑上表示完成的任务
,而不是计算与该任务相同的逻辑值。如果调用者只关心任务的结果(或错误状态),这将强制调用者展开该任务,但如果您并不总是希望将其展开,则可以返回整个任务
。它实际上简化了代码,使Order
方法无法为您展开任务
public static IEnumerable<Task<Task>> Order2(this IEnumerable<Task> tasks)
{
var taskList = tasks.ToList();
var taskSources = new BlockingCollection<TaskCompletionSource<Task>>();
var taskSourceList = new List<TaskCompletionSource<Task>>(taskList.Count);
foreach (var task in taskList)
{
var newSource = new TaskCompletionSource<Task>();
taskSources.Add(newSource);
taskSourceList.Add(newSource);
task.ContinueWith(t => taskSources.Take().TrySetResult(t),
CancellationToken.None, TaskContinuationOptions.PreferFairness, TaskScheduler.Default);
}
return taskSourceList.Select(tcs => tcs.Task);
}
公共静态IEnumerable Order2(此IEnumerable任务)
{
var taskList=tasks.ToList();
var taskSources=new BlockingCollection();
var taskSourceList=新列表(taskList.Count);
foreach(任务列表中的var任务)
{
var newSource=new TaskCompletionSource();
taskSources.Add(newSource);
taskSourceList.Add(新闻源);
task.ContinueWith(t=>taskSources.Take().TrySetResult(t),
CancellationToken.None,TaskContinuationOptions.PreferFairity,TaskScheduler.Default);
}
返回taskSourceList.Select(tcs=>tcs.Task);
}
我的想法是,不要像这里那样使用
作为垃圾值来返回任务。但我看到的问题是,如果我试图询问任务.Result
,而原始任务
抛出了一个异常
,我将无法获得对任务
的引用,只能得到它抛出的异常虽然我可能需要仔细考虑这一点,然后才能真正投入思考实际上,我想我可能还没有完全理解TaskCompletionSource
。@KDecker在这段代码中,我们从未将Order2
返回的Task
设置为faulted。如果第一个完成故障的任务
,Order2
将返回一个成功运行完成的任务
,该任务有一个结果
保留故障的任务
。哦,我现在看到了(我想)。哇,这又是一段智力美学代码。再次感谢你!
public class TaskHoldingTaskCompletionSource<T> : TaskCompletionSource<T>
{
public Task OriginalTask { get; set; }
}
public static IEnumerable<Task<Task>> Order2(this IEnumerable<Task> tasks)
{
var taskList = tasks.ToList();
var taskSources = new BlockingCollection<TaskCompletionSource<Task>>();
var taskSourceList = new List<TaskCompletionSource<Task>>(taskList.Count);
foreach (var task in taskList)
{
var newSource = new TaskCompletionSource<Task>();
taskSources.Add(newSource);
taskSourceList.Add(newSource);
task.ContinueWith(t => taskSources.Take().TrySetResult(t),
CancellationToken.None, TaskContinuationOptions.PreferFairness, TaskScheduler.Default);
}
return taskSourceList.Select(tcs => tcs.Task);
}