《CLR via C#》之线程处理——任务调度器
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了《CLR via C#》之线程处理——任务调度器,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2822字,纯文字阅读大概需要5分钟。
内容图文
《CLR via C#》之线程基础——任务调度器
FCL提供了两个派生子TaskScheduler的类型:线程池任务调度器(thread pool task scheduler),和同步上下文任务调度器(synchronization context task scheduler)。默认情况下都使用线程池任务调度器。
线程池任务调度器
通过TaskScheduler的静态Default属性获得默认任务调度器的引用。
设置线程池限制
线程池永远不应该设置最大线程数,因为可能发生饥饿。虽然CLR提供了相关函数——ThreadPool静态方法(强烈不建议调用):GetMaxThreads,SetMaxThreads,GetMinThreads,SetMinThreads和GetAvailableThreads。
CLR线程数的默认值大约是1000个线程,基本可以认为是无限制。因为在32位进程最大用户空间为2GB,加载完Win32和CLR等DLLs后,大约剩余1.5GB地址空间。每个线程都需要超过1MB的内存(用户模式栈,线程环境块TEB),所以最多大约有1360个线程。试图创建更多会抛出OutOfMemoryException。64位的进程提供8TB地址空间,理论上可以创建千百万个线程。
如何管理工作者线程
- ThreadPool.QueueUserWorkItem方法和Timer类
总是将工作项放到全局队列中。采用先入先出(FIFO)策略来由工作者线程处理这个队列。防止多个工作者线程同时从全局队列取工作项,增加了一个线程同步锁(有时会成为性能瓶颈)。 - 默认TaskScheduler来调度Task对象
非工作者线程调度Task时,总是将它添加到全局队列。工作者线程调度Task时,将它添加到本地队列。
工作者线程获取Task步骤如下:- 首先从本地队列查找一个Task,以后入先出(LIFO)算法。由于工作者线程是唯一访问本地队列头的线程,所以无需同步锁。
- 如果本地队列空了,会尝试从另一个工作者线程的本地队列尾部“偷”一个Task,这个过程要求一个线程同步锁。
- 如果所有的本地队列都空了,那么工作者线程会使用FIFO算法,从全局队列提取一个工作项。如果全局队列也空了,那么工作者线程会进入睡眠状态,等待事情发生,如果睡眠时间太长,会自己醒了,并销毁自身以释放线程占用的资源。
同步上下文任务调度器
同步上下文任务调度器适合提供图形用户界面的应用程序。比如Form,WPF,Silverlight和Windows Store。它将所有任务都调度给GUI线程,使任务代码更新UI组件。通过执行TaskScheduler的静态方法FormCurrentSynchronizeContext来获得同步上下文任务调度器的引用。
internalsealedclassMyForm:Form
{
privatereadonlyTaskScheduler m_syncContextTaskScheduler;
publicMyForm()
{
// 获得一个同步上下文任务调度器的引用
m_syncContextTaskScheduler =TaskScheduler.FromCurrentSynchronizationContext();
Text="Synchronization Context Task Scheduler Demo";
Visible=true;Width=600;Height=100;
}
privateCancellationTokenSource m_cts;
protectedoverridevoidOnMouseClick(MouseEventArgs e)
{
if(m_cts !=null)
{// An operation is in flight, cancel it
m_cts.Cancel();712 PART V Threading
m_cts =null;
}
else
{// 操作正则进行,取消它
Text="Operation running";
m_cts =newCancellationTokenSource();
// 默认任务调度器调度的Task,在线程池执行
Task<Int32> t =Task.Run(()=>Sum(m_cts.Token,20000), m_cts.Token);
// 下面的任务使用同步上下文任务调度器,在GUI线程上执行
t.ContinueWith(task =>Text="Result: "+ task.Result,
CancellationToken.None,TaskContinuationOptions.OnlyOnRanToCompletion,
m_syncContextTaskScheduler);
t.ContinueWith(task =>Text="Operation canceled",
CancellationToken.None,TaskContinuationOptions.OnlyOnCanceled,
m_syncContextTaskScheduler);
t.ContinueWith(task =>Text="Operation faulted",
CancellationToken.None,TaskContinuationOptions.OnlyOnFaulted,
m_syncContextTaskScheduler);
}
base.OnMouseClick(e);
}
}
自定义TaskScheduler派生类
微软在Parallel Extensions Extras包中提供了大量和任务相关的示例代码,比如:
- IOTaskScheduler
将任务排队给线程池的I/O线程而不是工作者线程。 - LimitedConcurrencyLevelTaskScheduler
这个任务调度器不允许超过n(一个构造器参数)个任务同时执行 - OrderedTaskScheduler
派生自LimitedConcurrencyLevelScheduler,n为1。 - ThreadPerTaskScheduler
为每个任务 创建单独的线程,不使用线程池。 - PrioritizingTaskScheduler
调用Prioritize指出一个Task在所有普通任务之前处理,Deprioritize相反。
原文:http://www.cnblogs.com/qianzi067/p/5819799.html
内容总结
以上是互联网集市为您收集整理的《CLR via C#》之线程处理——任务调度器全部内容,希望文章能够帮你解决《CLR via C#》之线程处理——任务调度器所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。