2015-01-27 101 views
1

我有一個多線程應用程序必須執行3個不同類別的工作項目。分類一個爲最高優先級項目,類別項目涉及一個和類別ç項目涉及後後。這些工作項目使用任務排隊等待線程池。比方說,有10個類別C項目已在排隊,然後一個類別B項目被添加。在這種情況下,我想分類B項目之前處理的任何類別C項目。無論如何完成這個?任務工作項目優先級

+1

我想想有一個自定義排序 – 2015-01-27 00:34:01

+1

您可以創建自己的任務,生病嘗試隊列和執行一個線程安全列表的例子。 – DevEstacion 2015-01-27 00:34:39

+0

@LuisFilipe我還沒有真正嘗試過很多。我正在考慮使用Thread.Priority,但是,使用Google提示它可能不是一個好主意。所以我期待在這裏得到一些出發點。 – 2015-01-27 00:38:31

回答

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

實現對收集自己刪除。

+0

請注意,刪除也必須是線程安全的 – 2015-01-27 02:16:35

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和自定義比較爲自己的類。

希望它幫助

1

請看看我的基於List類的二分查找方法版本的解決方案。

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