Getting a link to the original Task after ordering Tasks to complete?

I asked a question a while ago about a method that orders List<Task<T>>>upon completion, which also returns intrepresenting an index completed Taskin the original List<Task<T>>.

I have a suspicion that I may not need to return this intone to determine which particular has Taskbeen completed, and that I can interrogate the returned one Taskfor this information.


As a side note, I have since changed the method for ordering a List<Task>. I initially used Task<T>that I returned boolfor presentation if I Task<T>was successful in my work or not. Now I'm just throwing a subclass Exceptionthat provides more information on how and why the crash Task.

My idea on this issue arose because when Task<int>it throws out of this method Exception, I can’t determine which one I’ve Taskchosen Exception, because I can’t poll Task<int>.Resultfor the original index Task.

So, if I can interrogate Task<int>(now just plain Task) which is returned for Task, it links to the original list, I can just compare the links.


Here is a method as it is now (credit for Servy for the source code for this method. Also maybe this blog post is from Jon Skeet)

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

My first problem is what this method uses TaskCompletionSource<T>to track TResult Taskfrom a list of parameters. Seeing that List<Task>>now it does not return a value and uses it Exception, it is useless, although its use is inevitable, because there is no asymmetrically parameterized one TaskCompletionSource<T>. But this is not a problem, because I can just return some basket value.

So, to the question itself , can I interrogate Task<(unused return value)>to get a link to Taskwhich one it is tracking?


, , TaskCompletionSource<T> Task, . "" Task.

TaskCompletionSource<T>, , Task, ?

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

, 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);
}
+3

Source: https://habr.com/ru/post/1657670/


All Articles