【问题标题】:How to get current running task in a blockingqueue of C#?如何在 C# 的阻塞队列中获取当前正在运行的任务?
【发布时间】:2012-10-06 05:45:53
【问题描述】:

我想获取我正在阻塞队列中添加的当前正在执行的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
    }
}

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

【问题讨论】:

  • 您能否提供一个简短的代码示例,其中包含您想要“获取当前正在执行的任务”的 cmets?
  • 您希望如何停止正在运行的任务?
  • 我的意思是取消一个正在运行的任务......然后用相同的凭据重新启动它......如果有一个优雅的方式,分享它吗?
  • 不,我相信实际上没有什么好的方法可以做到这一点。而且我认为取消Task 然后再次重新启动它也行不通。一旦Task 完成,无论成功与否,它都完成了。

标签: c# task-parallel-library blockingqueue


【解决方案1】:

如果你指的是BlockingCollection&lt;T&gt;,你不能(直接)。当您调用Take()(或通过GetConsumingEnumerable() 获取下一项)时,该项(任务?)实际上已从底层连接中移除。

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

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

【讨论】:

  • 实际上我在优先级调度程序中使用集合。我在其中分配具有不同优先级的任务。一旦他们开始运行,我需要知道什么任务正在以什么优先级运行。不知道take()怎么用,还有什么想法吗?
  • @faizanjehangir 您可以将自己的基础集合提供给BlockingCollection&lt;T&gt;。如果你在下面使用了 PriorityQueue,它会自动为你处理优先级调度(不需要知道已经执行了什么)
  • 我已经对帖子进行了编辑,我想根据优先级停止和恢复任务,例如如果有更高优先级的新任务到达,低级停止并让任务执行,然后自行恢复......
  • @faizanjehangir Task 没有公开任何停止或重新启动任务的机制。一旦你开始一个任务,它就会一直运行直到完成。
  • @faizanjehangir 您必须自行管理所有这些信息。我想你会发现试图停止已经在运行的任务将是一场噩梦,因为 TPL 根本不打算处理这个问题。 CancelationToken 的目的不是暂停,而是完全取消操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
相关资源
最近更新 更多