如何在C#的阻塞队列中获取当前运行的任务?

时间:2012-10-05 21:08:14

标签: c# task-parallel-library blockingqueue

我想得到我在blockqueue中添加的当前正在执行的Task,它是如何完成的?

编辑:我正在使用此优先级调度程序,并添加具有不同优先级的多个任务:

public class PriorityScheduler : TaskScheduler
{
    public static PriorityScheduler Highest = new PriorityScheduler(ThreadPriority.Highest);
    public static PriorityScheduler AboveNormal = new PriorityScheduler(ThreadPriority.AboveNormal);
    public static PriorityScheduler Normal = new PriorityScheduler(ThreadPriority.Normal);
    public static PriorityScheduler BelowNormal = new PriorityScheduler(ThreadPriority.BelowNormal);
    public static PriorityScheduler Lowest = new PriorityScheduler(ThreadPriority.Lowest);

    public static BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
    private Thread[] _threads;
    private ThreadPriority _priority;
    private readonly int _maximumConcurrencyLevel = Math.Max(1, Environment.ProcessorCount);

    public PriorityScheduler(ThreadPriority priority)
    {
        _priority = priority;
    }

    public override int MaximumConcurrencyLevel
    {
        get { return _maximumConcurrencyLevel; }
    }

    protected override IEnumerable<Task> GetScheduledTasks()
    {
        return _tasks;
    }

    protected override void QueueTask(Task task)
    {
        _tasks.Add(task);

        if (_threads == null)
        {
            _threads = new Thread[_maximumConcurrencyLevel];
            for (int i = 0; i < _threads.Length; i++)
            {
                int local = i;
                _threads[i] = new Thread(() =>
                {
                    foreach (Task t in _tasks.GetConsumingEnumerable())
                        base.TryExecuteTask(t);
                });
                _threads[i].Name = string.Format("PriorityScheduler: ", i);
                _threads[i].Priority = _priority;
                _threads[i].IsBackground = true;
                _threads[i].Start();
            }
        }
    }

    protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
    {
        return false; // we might not want to execute task that should schedule as high or low priority inline
    }
}

我想根据优先级停止和恢复任务,例如如果具有较高优先级的新任务到达,则较低的停止并让任务执行,然后自行恢复......

1 个答案:

答案 0 :(得分:2)

如果您指的是BlockingCollection<T>,则不能(直接)。当您致电Take()(或通过GetConsumingEnumerable()获取下一个项目)时,项目(任务?)实际上已从基础连接中删除。

如果您希望这样做,您需要拥有您的消费者商店并公开“当前任务”。

请注意,Parallel Extension Extras项目提供了一个很棒的QueuedTaskScheduler,可以在这里实现您的目标。它允许您创建优先级TaskScheduler实例,并为您处理所有计划。