任务队列。这怎么样? [英] TaskQueue. How is this bad?

查看:89
本文介绍了任务队列。这怎么样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经查看了QueuedTaskScheduler并且我非常困惑。

http://blogs.msdn.com/b/pfxteam/archive/2010/04/09/9990424.aspx [ ^ ]



所以我写了这个课来做我想做的事。

我想要的是一个课程,它会在后台排队任务并以较低的优先级顺序启动它们。同时管理最大并发性。



但是我还想允许在达到最大队列限制时同步(或不同步)执行提供的Action / Task 。



有人能告诉我这可能有什么不好或为什么我应该只使用TaskScheduler?



I''ve reviewed the QueuedTaskScheduler and I''m very confused.
http://blogs.msdn.com/b/pfxteam/archive/2010/04/09/9990424.aspx[^]

So I wrote this class to do what I wanted.
What I wanted is a class that will queue up tasks in the background and start them in order with a lower priority. Also managing a maximum concurrency.

But also I wanted to allow for the the provided Action/Task to be executed synchronously (or not) when a maximum queue limit is reached.

Can someone tell me how this might be bad or why I should simply use a TaskScheduler?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Utilities
{

	/// <summary>
	/// Acts as a producer-consumer for tasks...
	/// </summary>
	public class TaskQueue
	{
		readonly object _syncRoot = new Object();
		readonly Queue<Action> _actions = new Queue<Action>();
		readonly List<Thread> _tasks = new List<Thread>();

		int _maxConcurrency;
		public int MaxConcurrency
		{
			get
			{
				return _maxConcurrency;
			}
			set
			{
				Contract.Requires(value > 0);
				lock (_tasks)
					_maxConcurrency = value;
			}
		}

		int _maxTasks;
		public int MaxTasks
		{
			get
			{
				return _maxTasks;
			}
			set
			{
				Contract.Requires(value > 0);
				lock (_tasks)
					_maxTasks = value;
			}
		}

		public int Count {
			get {
				return _tasks.Count + _actions.Count;
			}
		}
		// Default limits to 4.
		public TaskQueue(int maxConcurrency = 4, int maxTasks = 24)
		{
			MaxConcurrency = maxConcurrency;
			MaxTasks = Math.Max(maxConcurrency,maxTasks);
		}

		void Cycle()
		{
			if (_tasks.Count < _maxConcurrency)
			{
				lock (_syncRoot)
				{
					if (_tasks.Count < _maxConcurrency && _actions.Any())
					{
						var task = new Thread(new ThreadStart(_actions.Dequeue()));
						_tasks.Add(task);
						task.IsBackground = true;
						task.Priority = ThreadPriority.Lowest;

						Task.Factory.StartNew(() =>
						{
							task.Start();
							task.Join();
							lock (_syncRoot)
								_tasks.Remove(task);
							Cycle();
						});
					}
				}
			}
		}

		public bool Queue(Action action, bool executeSynchronousIfLimitreached = true)
		{
			if(Count < MaxTasks) {
				lock (_syncRoot)
				{
					if (Count < MaxTasks)
					{
						_actions.Enqueue(action);
						Cycle();
						return true;
					}
				}
			}

			Debug.Print("Task limit reached: " + MaxTasks);
				
			if(executeSynchronousIfLimitreached)
				action();

			return false;
		}

	}
}

推荐答案





我喜欢你所做的但是我个人认为自定义线程管理和管理TPL任务的混合在这个例子中非常有问题。 TPL有很多很棒的功能,不需要所有的自定义管理。



虽然我没有尝试按线程优先顺序执行任务,但我想提几个可能会有所帮助的想法。



使用ParallelOptions,您可以管理任务的并发性。您还可以完全从TPL包装器管理优先级和其他线程方面。



a以下好链接:

http://aviadezra.blogspot.co.uk/2009/10/how-many-threads -tpl-concurrency.html [ ^ ]



其次,如果达到最大线程,同步执行某些内容的想法将无济于事。如果所有核心都忙于工作,那么你的任务就会等待,直到有空闲为止。我不确定你为什么要这样做,但后来我可能会遗漏一些东西。



我也会查看System.Collections.Concurrency的内容。使用ConcurrentBag会更好地保证线程安全,因为这一切都是为您完成的。另请参阅并发堆栈和队列。这些可能有所帮助。

System.Collections.Concurrency [ ^ ]



最后,我必须推荐BlockingCollection。基本上你可以在这里做的是将任务/动作/东西添加到集合中。然后你可以平行地枚举它。它将是线程安全的,只为您提供集合中的下一个项目。然后可以解析这个以进行处理。坚持TPL的美妙之处在于能够安全地取消依赖线程时相当成问题的操作。您还可以创建可以处理故障和清理的延续。



http://msdn.microsoft.com/en-us/library/dd267312.aspx [ ^ ]



所以,虽然不是直接解决方案,但我希望其中一些这很有用。祝你好运!
Hi,

I like what you have done however personally I feel the mix of custom thread management plus mangeing TPL tasks etc very problematic in this instance. TPL has many great features that do not require all the custom management.

Whilst I have not tried executing tasks in order of thread priority I would like to mention a couple of ideas that may help.

Using ParallelOptions you can manage the concurrency of your tasks. You can also manage the priority and other thread aspects purely from the TPL wrappers.

a good link is below:
http://aviadezra.blogspot.co.uk/2009/10/how-many-threads-tpl-concurrency.html[^]

Secondly, the idea of executing something synchronously if the max threads has been reached will not help too much. If the all cores are busy on jobs, your task is going to wait anyway until something is free. I am not sure why you would want to do this but then I might be missing something.

I would also look into the System.Collections.Concurrency stuff. Using the ConcurrentBag will be better for thread safety as this is all done for you. Also take a look at the Concurrent Stack and queue. These could help.
System.Collections.Concurrency[^]

Lastly, I must recommend the BlockingCollection. Basically what you can do here is add tasks / actions / stuff to the collection. You can then enumerate over it in parrallel. It will be thread safe and only give you the next item in the collection. This can then be parsed off for processing. The beauty of sticking with TPL is the ability to safely cancel actions that are rather problematic if relying on threads. You can also create continuations that can handle faults and clean up.

http://msdn.microsoft.com/en-us/library/dd267312.aspx[^]

So, whilst not a direct solution, I hope some of this is useful. Best of luck!


这篇关于任务队列。这怎么样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆