gpt4 book ai didi

c# - 在完成订购任务后获取对原始任务的引用?

转载 作者:太空狗 更新时间:2023-10-30 01:31:43 24 4
gpt4 key购买 nike

我问了a question前一段时间关于订购 List<Task<T>>> 的方法通过他们的完成,也返回一个 int代表完成的索引 Task在原文List<Task<T>>给出。

我觉得我可能不需要退回这个 int确定具体哪个Task已经完成,我可以查询返回的 Task获取此信息。


作为旁注,我已经改变了订购 List<Task> 的方法。 .我最初使用 Task<T> ,它返回了一个 bool代表如果Task<T>工作是否成功。我现在简单地抛出 Exception 的一个子类其中提供了更多关于如何以及为什么会出现 Task 的信息。失败的。

我对这个问题的想法来自于当一个 Task<int>从这个方法抛出一个 Exception我无法确定具体是哪个 Task扔了 Exception因为我无法审问 Task<int>.Result对于 Task的原始索引。

再说一次,如果我能审问 Task<int> (现在只是 Task )为 Task 返回它指的是原始列表中的内容,我可以简单地比较引用资料。


这是现在存在的方法(此方法的 original code 归功于 Servy。也可能是 Jon Skeet 的 blog post)

public static IEnumerable<Task<int>> OrderByCompletion(IEnumerable<Task> tasks)
{
var taskList = tasks.ToList();
var taskSources = new BlockingCollection<TaskCompletionSource<int>>();
var taskSourceList = new List<TaskCompletionSource<int>>(taskList.Count);

for (int i = 0; i < taskList.Count; i++)
{
var task = taskList[i];
var newSource = new TaskCompletionSource<int>();
taskSources.Add(newSource);
taskSourceList.Add(newSource);

int index = i;

task.ContinueWith(t =>
{
var source = taskSources.Take();

if (t.IsCanceled)
source.TrySetCanceled();
else if (t.IsFaulted)
source.TrySetException(t.Exception.InnerExceptions);
else if (t.IsCompleted)
source.TrySetResult(index);
}, CancellationToken.None, TaskContinuationOptions.PreferFairness, TaskScheduler.Default);
}

return taskSourceList.Select(tcs => tcs.Task);
}

我的第一个问题是此方法使用 TaskCompletionSource<T>追踪 TResultTask从参数列表。视为 List<Task>>现在不返回任何值并使用 Exception这是无用的,尽管它的使用是不可避免的,因为没有非通用参数化 TaskCompletionSource<T> 但这并不是真正的问题,因为我可以返回一些垃圾值。

那么,就问题本身而言,我可以询问 Task<(unused return value)> 吗?获得对 Task 的引用它跟踪?


据我所知 TaskCompletionSource<T>没有关于 Task 的信息它正在跟踪。它只是“看起来像”原来的 Task .

是子类化TaskCompletionSource<T>的唯一选择添加一个引用 Task 的属性它跟踪,在方法中设置属性的值,然后查询该属性以获取引用?

public class TaskHoldingTaskCompletionSource<T> : TaskCompletionSource<T>
{
public Task OriginalTask { get; set; }
}

最佳答案

只要看看 WhenAny 解决这个问题的方法就可以了。让该方法返回一个 Task,其结果是逻辑上表示完成的 Task,而不是计算与该任务相同的逻辑值。如果调用者只关心任务的结果(或错误状态),这会强制调用者解包该任务,但如果您并不总是希望它解包,则可以只返回整个 Task。它实际上简化了没有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);
}

关于c# - 在完成订购任务后获取对原始任务的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40030522/

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