0

I want to get the current executing Task that I am adding in the blockingqueue, how it can be done?

EDIT: I am using this priority scheduler, and adding multiple tasks with different priorities:

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

I want to stop and resume tasks depending upon there priorities, e.g. if a new task with higher priority arrives, the lower stops and lets the task execute and then resumes itself...

faizanjehangir
  • 2,771
  • 6
  • 45
  • 83
  • 2
    Can you provide a short code example with comments as to where you want to "get the current executing Task"? – Austin Salonen Oct 05 '12 at 21:11
  • How exactly do you expect to stop a running task? – svick Oct 05 '12 at 21:36
  • I mean cancel a running task....and then starting it again with the same credentials...if there is an elegant way, Do share it? – faizanjehangir Oct 05 '12 at 21:38
  • 1
    No, I believe there is actually no good way to do that. And I think canceling a `Task` and then restarting it again won't work either. Once a `Task` finishes, successfully or not, it's done. – svick Oct 05 '12 at 21:40

1 Answers1

2

If you are referring to BlockingCollection<T>, you can't (directly). When you call Take() (or get the next item via GetConsumingEnumerable()), the item (task?) is actually removed from the underlying connection.

You would need to have your consumer store and expose the "current task" if you want this to be available.

Note that the Parallel Extension Extras project provides a great QueuedTaskScheduler which may accomplish your goals here. It allows you to create prioritized TaskScheduler instances, and handles all of the scheduling for you.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Actually I am using the collection in a priority scheduler. In which I assign tasks with different priorities. I need to know what task is running with what priority once they start running. I do not know how to use take(), any other ideas? – faizanjehangir Oct 05 '12 at 21:15
  • @faizanjehangir You can provide your own underlying collection to `BlockingCollection`. If you used a PriorityQueue underneath, it would handle the priority scheduling automatically for you (without needing to know about what's already executing) – Reed Copsey Oct 05 '12 at 21:17
  • I have made an edit to the post, I want to stop and resume tasks depending upon there priorities, e.g. if a new task with higher priority arrives, the lower stops and lets the task execute and then resumes itself... – faizanjehangir Oct 05 '12 at 21:20
  • @faizanjehangir `Task` doesn't expose any mechanism for stopping or restarting a task . Once you start a Task, it runs until completion. – Reed Copsey Oct 05 '12 at 21:24
  • @faizanjehangir I would just worry about the **next** task that will execute, and not try to stop a task in process. – Reed Copsey Oct 05 '12 at 21:25
  • For that purpose I suppose cancellationtoken will be used...But for that I need to know which task is running currently in the scheduler so that the underlying thread priorities could be identified...any ideas? – faizanjehangir Oct 05 '12 at 21:28
  • 1
    @faizanjehangir You'd have to self-manage all of that information. I think you'll find trying to stop a task that's already running is going to be a nightmare, as the TPL is not intended to handle that at all. CancelationToken is not intended to *pause*, but to completely cancel an operation. – Reed Copsey Oct 05 '12 at 21:29
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/17626/discussion-between-faizanjehangir-and-reed-copsey) – faizanjehangir Oct 05 '12 at 21:30