任务工作项优先级

Task work item priorities

我有一个多线程应用程序,它必须执行 3 个不同类别的工作项。类别 A 是最高优先级的项目,类别 B 项目排在 A 之后,类别 C 项在 B 之后。这些工作项使用任务排队到线程池。假设队列中已有 10 个类别 C 项目,然后添加了一个类别 B 项目。在这种情况下,我希望类别 B 项目在任何类别 C 项目之前被处理。有办法实现吗?

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

像这样创建一个对象

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

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

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();

对集合执行您自己的删除操作。

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

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

排序集

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

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

希望对您有所帮助

请查看我基于 List class 的 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.");
    }));