Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按完成顺序排列任务后,是否获取对原始任务的引用?_C#_Exception Handling_Task Parallel Library_Task - Fatal编程技术网

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);
}