按完成时间排序任务,同时在参数列表中跟踪其索引?

时间:2016-04-22 17:18:10

标签: c# task-parallel-library ienumerable

我最近asked a question关于清理一些代码的可能性,代码是等待Task中的每个List<Task<T>>完成,但取消所有Task如果一个人返回了一些虚假的价值。

名为Servy quickly produced a method的用户,在完成时间内雄辩地命名List<Task<T>>。在仔细阅读了答案之后,我认为/我认为/理解这个方法。然后我开始使用该方法,但很快就意识到了问题。我需要能够在他们完成时识别Task。但是Servy建议的Order方法没有办法做到这一点(因为我无法将Order返回的任务延续与我最初提供的List<Task<>>进行比较。

所以我去更改方法以返回Tuple<T, int>,其中int表示提供的参数中Task的原始索引。

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

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

        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(new Tuple<T, int>(t.Result, i));
        }, CancellationToken.None, TaskContinuationOptions.PreferFairness, TaskScheduler.Default);
    }

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

// Usage
foreach(var task in myTaskList.OrderByCompletion())
    Tuple<Boolean, int> result = await task;

我面临的问题是,Tuple返回的索引似乎始终等于传递给Count的{​​{1}}的{​​{1}},无论是返回任务的顺序。

我认为由于这个问题我不能完全理解这种方法是如何起作用的,尽管看起来它应该可以正常工作。

任何人都可以解释这个问题并提供解决方案吗?

1 个答案:

答案 0 :(得分:2)

这是因为您在OMX_ERRORTYPE OMX::OnFillBufferDone( node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { ALOGV("OnFillBufferDone buffer=%p", pBuffer); omx_message msg; msg.type = omx_message::FILL_BUFFER_DONE; msg.node = node; msg.u.extended_buffer_data.buffer = buffer; msg.u.extended_buffer_data.range_offset = pBuffer->nOffset; msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen; msg.u.extended_buffer_data.flags = pBuffer->nFlags; msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp; //dump date code if(pBuffer->nFilledLen>0) { FILE *fp=NULL; fp=fopen("/data/video.yuv","a+"); if(fp) { fwrite((unsigned char *)pBuffer->pBuffer,1,pBuffer->nFilledLen,fp); fclose(fp); }else { ALOGE(" catch data is failure"); }/*...*/}}} 内使用i变量。

但是,当您创建Action<>时,不会执行此操作的代码,但是当任务完成时,变量Action的值为i(当{{1}时) } loop finished)。

您只需向taskList.Count添加额外的变量即可解决您的问题:

for

您可以阅读此question/answers了解详情。