任务工作项优先事项

时间:2015-01-27 00:31:15

标签: c# .net multithreading task thread-priority

我有一个多线程应用程序,必须执行3种不同类别的工作项。类别 A 是优先级最高的项目,类别 B 项目来自 A 和类别 C 项目之后即可。这些工作项使用Tasks排队到线程池。我们说,队列中已有10个类别 C 项目,然后添加了类别 B 项目。在这种情况下,我希望在任何类别 C 项目之前处理类别 B 项目。有没有完成这个?

3 个答案:

答案 0 :(得分:2)

您可以通过创建自己的队列进程来实现它。这只是一个代码模型。

创建一个像这样的对象

public class PrioritizableTask
{
    public PrioritizableTask(Task task, int taskPriority)
    {
        Task = task;
        Priority = taskPriority;
    }

    public int Priority { get; private set; }

    public Task Task { get; private set; }
}

然后创建另一个集合类并在其上实现一个新方法,就像这样。

public class PrioritizableTasksCollection : IList<PrioritizableTask>
{
    private static readonly List<PrioritizableTask> runners = new List<PrioritizableTask>();

    public void Add(PrioritizableTask item)
    {
        runners.Add(item);
    }

    public Task GetNextPriority()
    {
        var priorityTask = runners.OrderBy(x => x.Priority).FirstOrDefault();
        return priorityTask != null ? priorityTask.Task : null;
    }
}

一样消费
PrioritizableTasksCollection executors = new PrioritizableTasksCollection();
executors.Add(new PrioritizableTask(new Task(() => { }), 4));
executors.Add(new PrioritizableTask(new Task(() => { }), 3));
executors.Add(new PrioritizableTask(new Task(() => { }), 7));
executors.Add(new PrioritizableTask(new Task(() => { }), 5));
executors.Add(new PrioritizableTask(new Task(() => { }), 1));
executors.Add(new PrioritizableTask(new Task(() => { }), 2));
Task executeNext = executors.GetNextPriority();

在集合上实现您自己的删除。

答案 1 :(得分:2)

我一直在查看您的问题,但我找不到内置的线程安全排序集合。

所以我构建了一个基本的线程安全SortedSet<int>包装类。

排序集

public class MyThreadSafeSortedSet
{
    private SortedSet<int> _set = new SortedSet<int>(new MyComparer());
    private readonly object _locker = new object();

    public void Add(int value)
    {
        lock (_locker)
        {
            _set.Add(value);
        }
    }

    public int? Take()
    {
        lock (_locker)
        {
            if (_set.Count == 0)
                return null;
            var item = _set.First();
            _set.Remove(item);
            return item;
        }
    }
}

我构建了一个自定义比较器,它更喜欢偶数

public class MyComparer : Comparer<int>
{
    public override int Compare(int x, int y)
    {
        if (x % 2 == 0)
        {
            if (y % 2 == 0)
                return x - y;
            else
                return -1;

        }
        else
        {
            if (y % 2 == 0)
                return 1;
            else
                return x - y;

        }
    }
}

最后是两个主题。一个生产物品;另一个拿他们

static void Main(string[] args)
{

    MyThreadSafeSortedSet queue = new MyThreadSafeSortedSet();

    var task1 = Task.Run(() =>
        {
            Random r = new Random();
            for (int i = 0; i < 15; i++)
            {
                Task.Delay(100).Wait();
                var randomNumber = r.Next();
                queue.Add(randomNumber);
            }
            Console.WriteLine("I'm done adding");
        });
    var task2 = Task.Run(() =>
    {
        Random r = new Random();
        while (true)
        {
            var delay = r.Next(500);
            Task.Delay(delay).Wait();

            var item = queue.Take();
            Console.WriteLine("Took: {0}", item);
            if (item == null)
                break;
        }
    });

    Task.WaitAll(task2);
}

您可以为自己的类更改专用的SortedSet和自定义比较器。

希望有所帮助

答案 2 :(得分:1)

请根据List类的BinarySearch方法查看我的解决方案版本。

enum CategoryOfWorkItem: int { C = 0, B, A };

struct WorkItem : IComparer<WorkItem>
{
    public CategoryOfWorkItem Category;

    public int Compare(WorkItem x, WorkItem y)
    {
        return x.Category - y.Category;
    }

    public void AddTo(List<WorkItem> list)
    {
        int i = list.BinarySearch(this, this);
        if (i < 0) i = ~i;
        list.Insert(i, this);
    }
}

使用示例

List<WorkItem> list = new List<WorkItem>();

Task.Run(() =>
    {
        Random rand = new Random();
        for (int i = 0; i < 20; i++)
        {
            WorkItem item = new WorkItem();
            switch (rand.Next(0, 3))
            {
                case 0: item.Category = CategoryOfWorkItem.A; break;
                case 1: item.Category = CategoryOfWorkItem.B; break;
                case 2: item.Category = CategoryOfWorkItem.C; break;
            }

            lock (list)
            {
                item.AddTo(list);
            }

            Task.Delay(rand.Next(100, 1000)).Wait();
            Console.WriteLine("Put {0}", item.Category);
        }

        Console.WriteLine("Putting finished.");
    });

Task.WaitAll(Task.Run(() =>
    {
        Random rand = new Random();
        while (true)
        {
            WorkItem item;
            Task.Delay(rand.Next(500, 1000)).Wait();
            lock (list)
            {
                if (list.Count < 1) break;
                item = list[list.Count - 1];
                list.RemoveAt(list.Count - 1);
            }

            Console.WriteLine("Get {0}", item.Category);
        }

        Console.WriteLine("Getting finished.");
    }));