在最近的一个项目中,比较多的接触到了异步委托的调用。对其内部原理很模糊,于是乎就认真研究了一番,幸有点小悟。
什么是多线程?
当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。
比喻加深认识
假设有一个公司,公司里有很多各司其职的职员,那么我们可以认为这个正常运作的公司就是一个进程,而公司里的职员就是线程。一个公司至少得有一个职员吧,同理,一个进程至少包含一个线程。在公司里,你可以一个职员干所有的事,但是效率很显然是高不起来的,一个人的公司也不可能做大;一个程序中也可以只用一个线程去做事,事实上,一些过时的语言如fortune,basic都是如此,但是象一个人的公司一样,效率很低,如果做大程序,效率更低——事实上现在几乎没有单线程的商业软件。公司的职员越多,老板就得发越多的薪水给他们,还得耗费大量精力去管理他们,协调他们之间的矛盾和利益;程序也是如此,线程越多耗费的资源也越多,需要CPU时间去跟踪线程,还得解决诸如死锁,同步等问题。总之,如果你不想你的公司被称为“皮包公司”,你就得多几个员工;如果你不想让你的程序显得稚气,就在你的程序里引入多线程吧!
在c#中是怎么使用的?
其实,在c# 中,线程的使用还是挺简单。它的操作都包含在System.Threading名字空间中,所以,首先需要导入这个名字空间。
怎么创建一个线程?
Thread th =new Thread(new ThreadStart(方法名));
也可以在构造方法里写一个匿名委托实例化如:
Thread th = new Thread(delegate() {处理逻辑代码});
关于线程的启动,可以有参数和无参数的,csdn博客中,周公讲的不错,链接如下
http://blog.csdn.net/zhoufoxcn/article/details/4402999
同时它还有几个常用的方法
Start():启动线程
Sleep(int):静态方法,暂停当前线程指定的毫秒数
Abort():通常使用该方法来终止一个线程,这个方法终止后,不能重新再start,否则异常。
Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复
Resume():恢复被Suspend()方法挂起的线程的执行
Join()等待当前线程,知道它执行完成。
线程的几个常见状态
Aborted:线程已停止
AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止
Background:线程在后台执行,与属性Thread.IsBackground有关
Running:线程正在正常运行
Stopped:线程已经被停止
StopRequested:线程正在被要求停止
Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行)
SuspendRequested:线程正在要求被挂起,但是未来得及响应
Unstarted:未调用Thread.Start()开始线程的运行
WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态
线程的优先级设置
当线程之间争夺CPU时间时,CPU按照是线程的优Highest,AboveNormal,Normal,BelowNormal,Lowest先级给予服务的。在C#应用程序中,用户可以设定5个不同的优先级,由高到低分别是,在创建线程时如果不指定优先级,那么系统默认为ThreadPriority.Normal。给一个线程指定优先级
同步和异步。
我一直都很模糊着两个的概念。也不是很清楚这同步异步与线程之间的关系。。。
原来,同步和异步,跟线程没有直接的关系。这两个概念似乎源于操作系统通信里面。
同步
由于程序中的代码区在线程中是可以共用的,所以,当多个线程访问同一个块代码时可能出现错误和异常,故此有了同步解决方案。在c#中,有两个关键字可用,一个Lock,一个是Monitor,其实内质上,Lock也是在调用Monitor的东西。用Monitor的Enter方法锁定一个对象,Exit释放一个对象。当用这个Monitor来锁定对象后,其他线程只有等待,待执行完成后,CPU根据排队线程的先后顺序执行。
而异步又是怎么回事?
有个比喻,说是,你妈叫你回家吃饭,你可以回也可以不回。你妈照样吃饭。
在网站中,一个视频还在加载中,用户也可以操作其他的东西。。
在WinForm中,若有某个处理过程需要花费很久的时间,而又不至于让前端UI无法卡死等待,可采用多线程异步模式。
http://www.dzsc.com/data/html/2009-11-5/79938.html
using System;
using System.Threading;
namespace AsyncDelegateDemo
{
delegate void AsyncFoo(int i);
class Program
{
/// ﹤summary﹥///
/// /// 输出当前线程的信息 ///
/// ﹤/summary﹥ ///
/// ﹤param nAME="name"﹥方法名称﹤/param﹥
static void PrintCurrThreadInfo(string name)
{
Console.WriteLine("Thread Id of " + name + " is: " + Thread.CurrentThread.ManagedThreadId + ", current thread is " + (Thread.CurrentThread.IsThreadPoolThread ? "" : "not ") + "thread pool thread.");
}
/// 测试方法,Sleep一定时间
/// ﹤/summary﹥
/// ﹤param name="i"﹥Sleep的时间﹤/param﹥
static void Foo(int i)
{
PrintCurrThreadInfo("Foo()");
Thread.Sleep(i);
}
/// ﹤summary﹥
/// 投递一个异步调用
/// ﹤/summary﹥
static void PostAsync()
{
AsyncFoo caller = new AsyncFoo(Foo);
caller.BeginInvoke(1000,
new AsyncCallback(FooCallBack), caller);
}
static void Main(string[] args)
{
PrintCurrThreadInfo("Main()");
for (int i = 0; i < 10; i++)
{
PostAsync();
}
Console.ReadLine();
}
static void FooCallBack(IAsyncResult ar)
{
PrintCurrThreadInfo("FooCallBack()");
AsyncFoo caller = (AsyncFoo)ar.AsyncState;
caller.EndInvoke(ar);
}
}
}
初步研究了异步委托后,发现异步委托是在线程池中新开一个线程.那么异步委托和多线程又有什么区别呢?为什么又要加个异步委托呢,用多线程就行了.在Google搜索到以下文字.
1.异步请求一般用在IO等耗时操作上,他的好处是函数调用立即返回,相应的工作线程立即返还给系统以供重用。由于系统的线程资源是非常宝贵的,通常有一定的数目限制,如.net默认是25。若使用异步方式,用这些固定数目的线程在固定的时间内就可以服务更多的请求,而如果用同步方式,那么每个请求都自始至终占用这一个线程,服务器可以同时服务的请求数就少了。当异步操作执行完成后,系统会从可用线程中选取一个执行回调程序,这时的这个线程可能是刚开始发出请求的那个线程,也可能是其他的线程,因为系统选取线程是随机的事情,所以不能说绝对不是刚开始的那个线程。多线程是用来并发的执行多个任务。
(注:摘自http://www.itwenku.com/net/5/21930.htm),请达人们给菜鸟解惑.谢谢
. 2.NET系统提供的多线程机制ThreadPool就是帮助你简化这些线程控制细节的,而几乎所有的.NET异步编程都是通过ThreadPool实现的。(摘自知秋一叶)
3.线程池的实现方法与线程是不一样的.初始化时在线程池里的线程为0.当进程需要一个线程时,创建一个线程,由此线程执行用户的方法.需要注意的是,此线程执行完后并不立即销毁,而是挂起等待,如果有其他方法需要执行,回唤醒进行处理.只有当它等到40秒(没有官方记录,有可能是其它数字)还没有任务执行时才唤醒自己,并销毁自己,释放资源.当然,如果线程池中的线程不够处理任务时,会再次创建一个新线程进行执行.详细的介绍请看
4.同步 例子
http://www.cnblogs.com/michaelxu/archive/2008/09/20/1293716.html