线程系列06,通过CLR代码查看线程池及其线程
2014-09-22 16:26
302 查看
在"线程系列04,传递数据给线程,线程命名,线程异常处理,线程池"中,我们已经知道,每个进程都有一个线程池。可以通过TPL,ThreadPool.QueueUserWorkItem,委托与线程池交互。本篇体验:通过查看CLR代码来观察线程池及其线程。
□ 通过编码查看线程池和线程
使用ThreadPool的静态方法QueueUserWorkItem把线程放入线程池,来看线程池线程和主程序线程的执行情况。
○ 用QueueUserWorkItem方法加入线程池的线程是后台线程
○ 一旦主线程结束,后台线程随即结束
○ 在主程序for语句块中,有2个线程已被创建并执行
让主线程和线程池线程都Sleep一段时间。
○ 线程池中的线程依然是后台线程
○ 让主线程Sleep一段时间后,线程池的线程在主线程结束之前得以执行
再让主线程Sleep更长的一段时间。
当主线程Sleep的时间更长后,线程池有更多的线程被执行。
□ 使用"即时窗口"查看CLR中的线程池和线程
以上,通过编码查看线程池和线程,实在是太不方便。我们可以在"即时窗口"中,借助"SOS调试扩展"来观察CLR中的线程池和线程。
→在"Thread.Sleep(r.Next(1000, 3000))"打上断点
→点击"启动"
→当代码运行到断点处,点击"调试"--"窗口"--"即时",打开"即时窗口"
→输入如下命令,加载"SOS调试扩展"
关于"SOS调试扩展"的使用,可参考"调试查看CLR运行代码"。
→输入如下命令,查看线程池
○ Worker Thread显示当前线程池中的线程状况
○ Work Request in Queue显示当前队列中的线程
→输入如下命令,查看所有线程
○ MTA (Finalizer)表示由GC回收的线程
○ MTA (Threadpool Worker) 表示线程池中的线程
□ 查看CLR托管堆上的所有线程类型
→输入如下命令查看CLR托管堆上的所有线程类型
□ 查看CLR托管堆上线程池实例
→找到System.ThreadPoolWorkQueue,复制其前面的MT代码
→输入如下命令,查看线程池实例的堆地址、数量等
□ 查看CLR托管线程池地址
→复制System.Threading.ThreadPoolWorkQueue的托管堆地址
→输入如下命令查看CLR托管线程池地址内容
线程系列包括:
□ 通过编码查看线程池和线程
使用ThreadPool的静态方法QueueUserWorkItem把线程放入线程池,来看线程池线程和主程序线程的执行情况。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("主线程开始");
for (int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem(SayHello, i);
}
Console.WriteLine("主线程结束");
}
static void SayHello(object arg)
{
int n = (int) arg;
Console.WriteLine("线程{0}接收到的参数是:{1},是否是后台线程:{2}",
Thread.CurrentThread.ManagedThreadId,
n,
Thread.CurrentThread.IsBackground);
}
}
○ 用QueueUserWorkItem方法加入线程池的线程是后台线程
○ 一旦主线程结束,后台线程随即结束
○ 在主程序for语句块中,有2个线程已被创建并执行
让主线程和线程池线程都Sleep一段时间。
class Program
{
static Random r = new Random();
static void Main(string[] args)
{
Console.WriteLine("主线程开始");
for (int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem(SayHello, i);
}
Thread.Sleep(r.Next(250, 500));
Console.WriteLine("主线程结束");
}
static void SayHello(object arg)
{
Thread.Sleep(r.Next(250, 500));
int n = (int) arg;
Console.WriteLine("线程{0}接收到的参数是:{1},是否是后台线程:{2}",
Thread.CurrentThread.ManagedThreadId,
n,
Thread.CurrentThread.IsBackground);
}
}
○ 线程池中的线程依然是后台线程
○ 让主线程Sleep一段时间后,线程池的线程在主线程结束之前得以执行
再让主线程Sleep更长的一段时间。
static void Main(string[] args)
{
Console.WriteLine("主线程开始");
for (int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem(SayHello, i);
}
Thread.Sleep(r.Next(1000, 3000));
Console.WriteLine("主线程结束");
}
当主线程Sleep的时间更长后,线程池有更多的线程被执行。
□ 使用"即时窗口"查看CLR中的线程池和线程
以上,通过编码查看线程池和线程,实在是太不方便。我们可以在"即时窗口"中,借助"SOS调试扩展"来观察CLR中的线程池和线程。
→在"Thread.Sleep(r.Next(1000, 3000))"打上断点
→点击"启动"
→当代码运行到断点处,点击"调试"--"窗口"--"即时",打开"即时窗口"
→输入如下命令,加载"SOS调试扩展"
关于"SOS调试扩展"的使用,可参考"调试查看CLR运行代码"。
→输入如下命令,查看线程池
○ Worker Thread显示当前线程池中的线程状况
○ Work Request in Queue显示当前队列中的线程
→输入如下命令,查看所有线程
○ MTA (Finalizer)表示由GC回收的线程
○ MTA (Threadpool Worker) 表示线程池中的线程
□ 查看CLR托管堆上的所有线程类型
→输入如下命令查看CLR托管堆上的所有线程类型
□ 查看CLR托管堆上线程池实例
→找到System.ThreadPoolWorkQueue,复制其前面的MT代码
→输入如下命令,查看线程池实例的堆地址、数量等
□ 查看CLR托管线程池地址
→复制System.Threading.ThreadPoolWorkQueue的托管堆地址
→输入如下命令查看CLR托管线程池地址内容
线程系列包括:
线程系列01,前台线程,后台线程,线程同步
线程系列02,多个线程同时处理一个耗时较长的任务以节省时间
线程系列03,多线程共享数据,多线程不共享数据
线程系列04,传递数据给线程,线程命名,线程异常处理,线程池
线程系列05,手动结束线程
线程系列06,通过CLR代码查看线程池及其线程
线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步
线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁
线程系列09,线程的等待、通知,以及手动控制线程数量线程系列10,无需显式调用线程的情形
相关文章推荐
- Spring代码实例系列-06:通过注解@Component、@Controller、@Service和@Repository定义bean,@Autowire装配bean
- [导入]CLR探索系列:GC Heap架构及其实现(垃圾回收系列)
- 通过MySQL自带工具perror查看错误代码对应的信息
- 通过CLR与托管代码思软件开发学习
- 细说多线程(四)—— CLR线程池的工作者线程
- C#线程系列讲座(3):线程池和文件下载服务器
- CLR探索系列:GC Heap架构及其实现(垃圾回收系列)
- 简单线程系列3-可变尺寸的线程池
- (转)C#线程系列讲座(3):线程池和文件下载服务器
- 线程锁的是对象(线程) synchronized 通过锁对象来锁代码
- # include <errno.h >查看错误代码errno是调试程序的一个重要方法。当Linux C API函数发生异常时,一般会将errno变量赋值一个整数,不同的值表示不同的含义,可以通过查看
- 通过远程线程向其他进程注入代码
- 通过DBCO配置链接信息用Native SQL访问外部数据库的代码示例及其相关notes
- CLR探索系列:Windbg+SOS动态调试分析托管代码 (转)
- CLR via C# 读书笔记 1-1 何时使用线程或者线程池
- CLR探索系列:Windbg+SOS动态调试分析托管代码 -- cnblog
- 通过进程ID查看进程信息,调出进程线程集合,查看进程模块,并对其进行操作!
- 查看当前线程的最后错误代码
- [转]C#线程系列讲座(3):线程池和文件下载服务器