使用System.Threading.Task将工作项排队到线程池

时间:2013-07-11 08:37:59

标签: .net multithreading task-parallel-library threadpool portable-class-library

我想知道哪个(如果有的话)是使用System.Threading.Task对象将工作项(委托)排队到.Net 4.5中的线程池的最直接的方法。我想要做的就是用ThreadPool.QueueUserWorkItem() s复制Task方法的排队功能。如果我错了,请纠正我,但据我所知,使用此方法排队的工作项目保证按照他们入队的顺序执行(也许我对多处理器场景完全错误)。我必须使用Task来编写行为相同的代码。

我正在开发一个可移植的类库,这就是为什么我不能使用ThreadPool.QueueUserWorkItem(),而是我必须依靠Task来实现这个目标。你会建议什么技术?默认任务调度程序是否适合此要求?

2 个答案:

答案 0 :(得分:3)

ThreadPool不需要以与调度完全相同的顺序执行委托(至少我没有在文档中找到任何保证)。但据我所知,这几乎就是它的表现。

Task s(默认为TaskScheduler)更复杂,因为它们使用以LIFO顺序处理的线程本地队列。如果要确保所有Task都转到全局FIFO队列,可以使用TaskCreationOptions.PreferFairness。但同样,没有记录这究竟是做什么的,所以细节可以改变。

答案 1 :(得分:1)

你问的是任务已经完成的事情。 Task本质上是一个lambda的包装器,默认情况下排队等待在ThreadPool上执行。最重要的是,Tasks添加了延续,异常处理,取消和许多便利功能,使多线程变得更加容易。

如果您不想使用ThreadPool,您可以创建自己的TaskScheduler并在创建新任务时使用它。 TaskScheduler实际上接收一个Task并安排它执行。

默认的TaskScheduler使用ThreadPool.QueueUserWorkItem加上一些工作窃取魔法和多个队列处理。其他实现可以使用优先级队列,在最大或最小线程数或其作者想要使用的任何技术上设置自己的限制。

修改

我从一开始就没有注意到 Portable 部分。所以问题是“PCL是否提供了使用ThreadPool的TaskScheduler,还是我必须创建自己的”?

.NET 4+提供了ThreadPoolTask​​Scheduler。不幸的是,PCL子集似乎缺少这一点。看起来您可能必须创建自己的TaskScheduler或使用Nuget Package来添加特定于平台的实现。

不知何故,我认为ThreadPoolTask​​Scheduler对Windows Phone项目来说是个不错的选择

在使用Resharper和.NET的调试符号进行一些diggind之后,我认为PCL自己找到任何可用的平台TaskScheduler实现。

在.NET 4.0中,TaskScheduler.Default返回ThreadPoolTask​​Scheduler的实例,这是一个内部BCL类。在PCL子集中,TaskScheduler.Default返回null并且ThreadPoolTask​​Scheduler不可用。

ThreadPoolTask​​Scheduler的源代码可以从Microsoft的参考源服务器获得,但您也可以在dotnetframework.org

快速浏览它。

我创建了一个PCL类,它返回一个新任务,并从.NET 4.5控制台应用程序调用它,以查看它将使用的TaskScheduler。我发现PCL类实际上使用了ThreadPoolTask​​Scheduler。

我还没有尝试使用Windows 8或Windows Phone 8项目,虽然我怀疑我会得到每个平台的默认TaskScheduler。