VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • C#教程之.net 多线程的使用(Thread)(2)

ioThreads); Console.WriteLine(String.Format("可以使用的工作线程: {0}; 可用 I/O 线程: {1}", workerThreads, ioThreads));
复制代码

执行上面的代码可以得带结果如下:

可创建最大线程数: 2047; 最大 I/O 线程: 1000
最小线程数: 4; 最小 I/O 线程: 4
可以使用的工作线程: 2047; 可用 I/O 线程: 1000

3.设置线程池初始化大小

我们为什么要设置线程池的大小呢?其实我们计算机并不是只运行你一个软件,你的给其他软件预留线程池,一般我们开发的时候使用的线程数是使用 8条、16条、32条和64条。不建议大于64条,毕竟老式的计算机支持有限,如果你计算机线程有2000多,你完全可以分配256以下的线程数。下面我们来看下如何设置。

复制代码
 #region 设置初始化线程
            ThreadPool.SetMaxThreads(8, 8);//最小也是CPU核数
            ThreadPool.SetMinThreads(4, 4);
            #endregion 
            #region 获取线程池当前设置 ,默认设置取决于操作系统和CPU 
            int workerThreads = 0;
            int ioThreads = 0;
            ThreadPool.GetMaxThreads(out workerThreads, out ioThreads);
            Console.WriteLine(String.Format("可创建最大线程数: {0};    最大 I/O 线程: {1}", workerThreads, ioThreads));

            ThreadPool.GetMinThreads(out workerThreads, out ioThreads);
            Console.WriteLine(String.Format("最小线程数: {0};    最小 I/O 线程: {1}", workerThreads, ioThreads));

            ThreadPool.GetAvailableThreads(out workerThreads, out ioThreads);
            Console.WriteLine(String.Format("可以使用的工作线程: {0};    可用 I/O 线程: {1}", workerThreads, ioThreads));
            #endregion 
复制代码

 

 执行结果如下:

可创建最大线程数: 8; 最大 I/O 线程: 8
最小线程数: 4; 最小 I/O 线程: 4
可以使用的工作线程: 8; 可用 I/O 线程: 8

4.线程池的使用

 线程池可以理解为,我们预先创建好指定数量的线程,给程序使用,当前正在使用的子线程一旦使用完成以后,要立即归还,下一个任务使用的时候,我在分配给这个任务。我们使用ManualResetEvent类来控制线程的使用与归还。具体看代码。

复制代码
  #region 多线程的使用
            Console.WriteLine("当前主线程id:{0}", Thread.CurrentThread.ManagedThreadId);
            //首先创建5个任务线程
            ManualResetEvent[] mre = new ManualResetEvent[]
            {
                new ManualResetEvent(false),
                new ManualResetEvent(false),
                new ManualResetEvent(false),
                new ManualResetEvent(false),
                new ManualResetEvent(false)
            };
            for (int i = 0; i < 5; i++)
            {
                ///false 默认是关闭的,TRUE 默认为打开的

                Thread.Sleep(300);
                ThreadPool.QueueUserWorkItem(t =>
                {
                    //lambda任务

                    Console.WriteLine("参数的内容是"+t);
                    Console.WriteLine("获取参数值((dynamic)t).num:" + ((dynamic)t).num);
                    int num = ((dynamic)t).num;
                    for (int j = 0; j < num; j++)
                    {
                        Thread.Sleep(2);//一件很耗时的事情
                    }
                    Console.WriteLine("当前子线程id:{0} 的状态:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);

                    //这里是释放共享锁,让其他线程进入
                    mre[i].Set();//可以理解为打开一个线程
                    //这里是打开共享锁,让其他线程进入
                    // mre[i].Reset();//可以理解为关闭一个线程
                    Console.WriteLine();
                }, new { num = (i + 1) * 10 });
                mre[i].WaitOne(3000); //单独阻塞线程,因为我们使用的是池,索引这里不使用这个,用法同委托异步
            }
            //注意这里,设定WaitAll是为了阻塞调用线程(主线程),让其余线程先执行完毕,
            //其中每个任务完成后调用其set()方法(收到信号),当所有
            //的任务都收到信号后,执行完毕,将控制权再次交回调用线程(这里的主线程)
           // ManualResetEvent.WaitAll(mre);不建议这么使用

            Console.ReadKey();
            #endregion
复制代码

 

 执行结果:

当前主线程id:1
参数的内容是{ num = 10 }
获取参数值((dynamic)t).num:10
当前子线程id:3 的状态:Background

参数的内容是{ num = 20 }
获取参数值((dynamic)t).num:20
当前子线程id:3 的状态:Background

参数的内容是{ num = 30 }
获取参数值((dynamic)t).num:30
当前子线程id:4 的状态:Background

参数的内容是{ num = 40 }
获取参数值((dynamic)t).num:40
当前子线程id:3 的状态:Background

参数的内容是{ num = 50 }
获取参数值((dynamic)t).num:50
当前子线程id:3 的状态:Background

 通过执行结果可以看出,第一次任务执行完成以后,把线程归还了,第二次任务分配的还是当前线程,但是第三次任务执行不过来了,我们从小分配了 一次线程。请根据结果分析。关于回调,线程等待使用方法同异步,救赎前一篇有介绍。

总结

1.本文主要演示了多线程和线程池的使用。夸线程访问(主要用于做进度条)。

2.本文介绍了使用多线程的利与弊及线程池的利与弊。

 3.Demo 下载地址


相关教程
关于我们--广告服务--免责声明--本站帮助-友情链接--版权声明--联系我们       黑ICP备07002182号