任务工作项优先级
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.");
}));
我有一个多线程应用程序,它必须执行 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.");
}));