自定义ActionBlock <t> </t>

时间:2012-12-12 12:19:35

标签: c# multithreading task-parallel-library .net-4.5 tpl-dataflow

我想实现优先级ActionBlock<T>。因此,我可以使用TInput条件优先考虑某些Predicate<T>项目 我看了 Parallel Extensions Extras SamplesGuide to Implementing Custom TPL Dataflow Blocks 但仍然没有弄清楚如何实现这种情况 ---------------------------- EDIT --------------------- ------
有一些任务,其中5个可以同时运行。当用户按下按钮时,一些(取决于谓词功能)任务应该以最优先的方式运行 实际上我写了这段代码

TaskScheduler taskSchedulerHighPriority;
ActionBlock<CustomObject> actionBlockLow;
ActionBlock<CustomObject> actionBlockHigh;
...
queuedTaskScheduler = new QueuedTaskScheduler(TaskScheduler.Default, 5);
taskSchedulerHigh = queuedTaskScheduler.ActivateNewQueue(0);
taskSchedulerLow = queuedTaskScheduler.ActivateNewQueue(1);
...
actionBlockHigh = new ActionBlock<CustomObject>(new Action<CustomObject>(method), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, SingleProducerConstrained = false, TaskScheduler = taskSchedulerHigh });
actionBlockLow = new ActionBlock<CustomObject>(new Action<CustomObject>(method), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, MaxMessagesPerTask = 1, TaskScheduler = taskSchedulerLow });
...     
if (predicate(customObject))
    actionBlockHigh.Post(customObject);
else
    actionBlockLow.Post(customObject);

但似乎优先权根本没有实现。
----------------------------编辑------------------
我发现当我使用这行代码的时候:

actionBlockHigh = new ActionBlock<AvlHistory>(new Action<AvlHistory>(SemaphoreAction), new ExecutionDataflowBlockOptions { TaskScheduler = taskSchedulerHigh });
actionBlockLow = new ActionBlock<AvlHistory>(new Action<AvlHistory>(SemaphoreAction), new ExecutionDataflowBlockOptions { TaskScheduler = taskSchedulerLow });

因为应用程序正确地观察了任务的优先级,但是一次只能执行一个任务,同时使用流程中显示的第一个代码块,导致应用程序同时运行5个任务但是按照不正确的优先级顺序。

actionBlockHigh = new ActionBlock<AvlHistory>(new Action<AvlHistory>(SemaphoreAction), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, TaskScheduler = taskSchedulerHigh });
actionBlockLow = new ActionBlock<AvlHistory>(new Action<AvlHistory>(SemaphoreAction), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5, TaskScheduler = taskSchedulerLow });

更新:
我要为MaxMessagesPerTask指定taskSchedulerLow坦克。

1 个答案:

答案 0 :(得分:7)

您的问题不包含许多细节,因此以下只是您可能需要的猜测。

我认为最简单的方法是在QueuedTaskScheduler from ParallelExtensionsExtras上运行两个ActionBlock个不同的优先级。您将使用谓词链接到高优先级,然后使用低优先级链接。另外,为了确保高优先级Task不等待,请设置低优先级块的MaxMessagesPerTask

在代码中,它看起来像:

static ITargetBlock<T> CreatePrioritizedActionBlock<T>(
    Action<T> action, Predicate<T> isPrioritizedPredicate)
{
    var buffer = new BufferBlock<T>();

    var scheduler = new QueuedTaskScheduler(1);

    var highPriorityScheduler = scheduler.ActivateNewQueue(0);
    var lowPriorityScheduler = scheduler.ActivateNewQueue(1);

    var highPriorityBlock = new ActionBlock<T>(
        action, new ExecutionDataflowBlockOptions
        {
            TaskScheduler = highPriorityScheduler
        });
    var lowPriorityBlock = new ActionBlock<T>(
        action, new ExecutionDataflowBlockOptions
        {
            TaskScheduler = lowPriorityScheduler,
            MaxMessagesPerTask = 1
        });

    buffer.LinkTo(highPriorityBlock, isPrioritizedPredicate);
    buffer.LinkTo(lowPriorityBlock);

    return buffer;
}

这只是您可以执行的操作的草图,例如,返回块的Completion行为不正确。