





















CCR第三个重要的组成部分是任务调度:当有接收器的port上有消息到达时如何生成任务和在有多个执行资源的机器上进行负载均衡。在CCR中有三个实现或者抽象任务调度的重要类。
例16.
var dispatcher = new Dispatcher(
0, // zero means use one thread per CPU, or 2 if only one CPU present
"sample dispatcher" // friendly name assgined to OS threads
);
var taskQueue
= new DispatcherQueue(var port
= new Port<int>();例16展示了如何创建Dispatcher和DispatcherQueue实例并用于调度任务。下面是对这个例子的每一步的描述:
当一个元素被投递到附加了接收器的port,port的实现中将会发生如下操作:
当上面的4步完成之后,生成的Task对象现在已经被调度逻辑分发(dealt)。
例17
// directly enqueue a task with an inlined method plus a parameter
taskQueue.Enqueue(
new Task<int>(5, item => Console.WriteLine(item))
);
上面这个例子我们展示了一个与例16中的调度功能等价的代码,但是不需要向port中投递任何元素。当数据已经准备好而且代码可以立即来处理它时,直接创建Task的实例很有用。CCR在Port.Post被调用时会调用接收器来创建Task实例,创建操作和例子中的类似。
一旦一个元素被放入DispatcherQueue,将会做如下操作:
CCR DispatcherQueue的实现允许根据一些预先定义的规则对任务执行进行速度控制。任务速度控制是CCR的关键功能,它使得程序可以把管理大队列的复杂性交给CCR调度器,从而优雅的处理大量的消息负载。速度控制策略是在DispatcherQueue创建时指定的。因为每个协调原语可以使用不同的DispatcherQueue,所以程序员可以给不同的处理器(handler)应用不同的策略。
/// <summary>
/// Specifies dispatcher queue task scheduling behavior
/// </summary>
public enum TaskExecutionPolicy
{
/// <summary>
/// Default behavior, all tasks are queued with no constraints
/// </summary>
Unconstrained = 0,
/// <summary>
/// Queue enforces maximum depth (specified at queue creation)
/// and discards tasks enqueued after the limit is reached
/// </summary>
ConstrainQueueDepthDiscardTasks,
/// <summary>
/// Queue enforces maximum depth (specified at queue creation)
/// but does not discard anny tasks. It forces the thread posting any tasks after the limit is reached, to
/// sleep until the queue depth falls below the limit
/// </summary>
ConstrainQueueDepthThrottleExecution,
/// <summary>
/// Queue enforces the rate of task scheduling specified at queue creation
/// and discards tasks enqueued after the current scheduling rate is above the specified rate
/// </summary>
ConstrainSchedulingRateDiscardTasks,
/// <summary>
/// Queue enforces the rate of task scheduling specified at queue creation
/// and forces the thread posting tasks to sleep until the current rate of task scheduling falls below
/// the specified average rate
/// </summary>
ConstrainSchedulingRateThrottleExecution
}
例26.
void ThrottlingExample()
{
int maximumDepth = 10;
Dispatcher dispatcher = new Dispatcher(0, "throttling example");
DispatcherQueue depthThrottledQueue = new DispatcherQueue("ConstrainQueueDepthDiscard",
dispatcher,
TaskExecutionPolicy.ConstrainQueueDepthDiscardTasks,
maximumDepth);
Port
<int> intPort = new Port<int>();例26中,我们创建了一个Dispatcher实例和一个DispatcherQueue实例,但是我们指定了一个ConstrainQueueDepthDiscardTasks任务执行策略,ConstrainQueueDepthDiscardTasks是一个策略选项。然后我们附加了一个持久化的接收器,并且以最快的速度投递了100万个元素。如果没有指定策略,一百万个任务将会被调度到机器的所有CPU上,并且dispatcher queue的深度将会增长到非常大。当指定了策略的时候,CCR将会抛弃最旧的任务,而且只会保持最新的10个任务执行。这种情况在只有最新的消息是有效的情况下是很有用的(通知、定时器等等)。
重要:depthThrottledQueue实例是提供给Arbiter.Activate方法将这个队列和指定的策略关联在一起,并将队列和用户在收到元素时生成Task对象的一个单元素接收器关联在一起。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。