一起谈.NET技术,闲话“多线程”

一,摘要

        圣殿骑士首先向大家说声对不起,由于最近身体不适,同时也因为这些天一直在研究微软的云计算平台Windows Azure(公司项目需要),所以暂停了更新WPF 基础到企业应用系列索引,不过经过这几天的调节,尤其是到海边去晒了晒太阳,现在又开始继续发文了,大家有兴趣也可以去看看漂亮的大海图片工作之余的闲暇,今天这篇文章不是专业谈多线程,只是应一些朋友的要求对上篇文章WPF 基础到企业应用系列4——WPF千年轮回进行一些额外的补充,如果有时间,可以单独写一个专题来详细深入多线程的应用,当然由于自己才疏学浅,但渴求对自己知识的纠正和提高,所以发布出来。如有不对的地方,也希望大家多多海涵!

二,提纲

一,摘要

二,提纲

三,基本概念

四,多线程实践

五,总结

三,基本概念

什么是进程?

“进程”是操作系统的最基本的,也是最重要的概念之一。简单来说一个进程就是你正在执行的应用程序,一个进程里面包括一个或多个线程。系统中的一个进程肯定对应着一个应用程序,但同一个应用程序可以有多个进程。所以我们要清楚,进程和程序是相关联的,但并不是同一个概念。即应用程序被加载到内存中后叫进程。

什么是线程?

线程简单来说就是程序中的一个执行流,每个线程都有自己的专有寄存器同时代码区是共享的,即不同的线程可以执行同样的函数和访问同样的变量。 即进程被CPU处理时叫线程。

什么是多线程? 

 多线程简单的说就是在一个程序中包含多个程序流,可以把一个复杂的操作分成多个细节操作,这些细节操作可以并行的执行,从而节约时间和提高效率。

多线程优点:

 线程可以有以下一些好处:可以提高CPU的利用率。在一个多线程程序中,一个线程处于等待的时候,CPU可以运行其它的线程来处理,这样就节约了时间和提高了程序的效率,同时也提高了用户的体验。

多线程缺点: 

1,线程越多,内存占用越大;

2,多线程的运行需要互相协调和统一管理,CPU会额外跟踪线程;
3,线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的种种问题;
4,线程太多会导致控制的复杂度增加,会引发不必要的Bug;

5,在32位的操作系统和64位的操作系统执行的线程、版本不同的操作系统之间执行的线程等都有所差异,执行顺序也有差异。

重要概念(本篇不重点讲解)

Start():启动线程;
Sleep(int):暂停当前线程指定的毫秒数;
Abort():通常使用该方法来终止一个线程,但容易出错;
Suspend():挂起线程,需要时可以恢复;
Resume():恢复被Suspend()方法挂起的线程;

程的优先级可以定义为ThreadPriority枚举的值,即Highest、AboveNormal、Normal、BelowNormal和 Lowest;

创建线程可以用如下三种方式:Thread、ThreadPool、Timer;

.NET Framework内置提供了三种Timer:System.Windows.Forms.Timer、System.Timers.Timer和System.Threading.Timer;

线程同步lock,Monitor,同步事件EventWaitHandler,互斥体Mutex、线程池等的使用;

四,多线程实践

        在本文中我们会通过11个小Demo来讲解一下多线程的实践,讲得不是很全面,只是希望给大家一个参考。由于比较简单,所以我就不添加累赘的文字介绍,这样大家看起来也比较舒畅。我会在文章后面附上代码,大家可以下载进行查看和调试。

这个11个方法都通过Form1_Load调用,如下面的代码和图片:

private void Form1_Load(object sender, EventArgs e){    DoWithEasy();    DoWithParameter();    DoWithTimer();    DoWithThreadPool();    DoWithThreadPoolParameter();    DoWithAnonymous();    DoWithLambda();    DoWithCommon();    DoWithAction();    DoWithFunc();    DoWithPredicate();}

创建一个简单的线程:

private void DoWithEasy(){Thread t = new Thread(new ThreadStart(this.DoSomethingWithEasy));    t.Start();}private void DoSomethingWithEasy(){MessageBox.Show("Knights Warrior");}

创建一个带参数的线程:

private void DoWithParameter(){Thread t = new Thread(new ParameterizedThreadStart(this.DoSomethingWithParameter));    t.Start("Knights Warrior");}private void DoSomethingWithParameter(object x){MessageBox.Show(x.ToString());}

 

使用Timer创建线程:

public void DoWithTimer()   {

System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();       timer.Interval = 1000;       timer.Tick += (x, y) =>       {MessageBox.Show("Knights Warrior");       };       timer.Start();   }

通过ThreadPool创建无参线程:

private void DoWithThreadPool(){ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomethingWithThreadPoolNO));}private void DoSomethingWithThreadPoolNO(object x){MessageBox.Show("Knights Warrior");}

通过ThreadPool创建有参线程:

private void DoWithThreadPoolParameter(){ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomethingWithThreadPoolParameter), "Knights Warrior");}private void DoSomethingWithThreadPoolParameter(object x){MessageBox.Show(x.ToString());}

通过匿名委托方式创建线程:

private void DoWithAnonymous(){ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object x)    {MessageBox.Show("Knights Warrior");    }));}

通过lambda的方式创建线程:

private void DoWithLambda(){ThreadPool.QueueUserWorkItem(new WaitCallback(x =>    {MessageBox.Show("Knights Warrior");    }));}

线程更新UI(自定义委托的方式):

private void DoWithCommon(){WaitCallback waitCallBack = new WaitCallback(this.InvokeMethod);ThreadPool.QueueUserWorkItem(waitCallBack, "Knights Warrior");}

private delegate void InvokeMethodDelegate(string name);private void InvokeMethod(object x){this.Invoke(new InvokeMethodDelegate(this.ChangeUIWithCommon), x.ToString());}

private void ChangeUIWithCommon(string name){this.lblMessage.Text = name;}

线程更新UI(通过Action委托)

private void DoWithAction()  {WaitCallback waitCallback = new WaitCallback(this.DoSomethingWithAction);ThreadPool.QueueUserWorkItem(waitCallback, "Knights Warrior");  }

private void DoSomethingWithAction(object x)  {this.Invoke(new Action<string>(this.ChangeUI), x.ToString());  }

private void ChangeUI(string message)  {this.lblMessage.Text = message;  }

线程更新UI(通过Func委托)

private void DoWithFunc(){WaitCallback waitCallback = new WaitCallback(this.DoSomethingWithFunc);ThreadPool.QueueUserWorkItem(waitCallback, "Knights Warrior");}

private void DoSomethingWithFunc(object x){Func<string, int> f = new Func<string, int>(this.GetFuncMessage);object result = this.Invoke(f, x.ToString());MessageBox.Show(result.ToString());}

private int GetFuncMessage(string message){this.lblMessage.Text = message;if (message == "Knights Warrior")    {return 1;    }else{return 0;    }}

线程更新UI(通过Predicate委托)

private void DoWithPredicate(){WaitCallback waitCallback = new WaitCallback(this.DoSomethingWithPredicate);ThreadPool.QueueUserWorkItem(waitCallback, "Knights Warrior");}

private void DoSomethingWithPredicate(object x){Predicate<string> pd = new Predicate<string>(this.GetPredicateMessage);object result = this.Invoke(pd, x);MessageBox.Show(result.ToString());}

private bool GetPredicateMessage(string message){this.lblMessage.Text = message;if (message == "Knights Warrior")    {return true;    }else{return false;    }}

概念注解:

Predicate 委托

定义:public delegate bool Predicate<T>(T obj);

表示定义一组条件并确定指定对象是否符合这些条件的方法。这个委托经常由 Array 和 List 类的几种方法使用,用于在集合中检索元素。

Func 委托

  定义:public delegate TResult Func<T, TResult>(T arg);
 

代码


delegate TResult Func<T>();
delegate TResult Func<T1,TResult>(T1 arg1);
delegate TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2);
delegate TResult Func<T1,T2,T3,TResult>(T1 arg1, T2 arg2, T3 arg3);
delegate TResult Func<T1,T2,T3,T4,TResult>T1 arg1, T2 arg2, T3 arg3, T4 arg4);

Func():封装一个不具有参数并返回 TResult 的类型值的方法。

Func<T, TResult> 封装一个具有一个参数并返回 TResult 的类型值的方法。

Action 委托

  定义:public delegate void Action<T>(T obj);

代码


delegate void Action<T>(T1 arg1);
delegate void Action<T1,T2>(T1 arg1, T2 arg2);
delegate void Action<T1,T2,T3>T1 arg1, T2 arg2, T3 arg3);
delegate void Action<T1,T2,T3,T4>T1 arg1, T2 arg2, T3 arg3, T4 arg4)

Action<T1, T2>:封装一个带有两个参数并且无返回值的方法。

这三个委托经常会用到,区分也很简单:
Predicate接受一个T的参数,返回一个bool值,可以用
Func实现此功能; 
Func接受1到4个参数,返回一个值; 

Action接受1到4个参数,无返回值;

五,总结

         这篇文章并没有什么深度和难度,只是对多线程进行了一下小结,如果大家想了解更多,我会单独详细写一些多线程相关的文章,当然由于本人知识有限,文中错误之处也敬请海涵!下一篇开始我们将继续更新WPF 基础到企业应用系列索引系列文章,如果有感兴趣的同仁,敬请关注!

时间: 2024-07-30 01:16:27

一起谈.NET技术,闲话“多线程”的相关文章

浅谈java中异步多线程超时导致的服务异常_java

在项目中为了提高大并发量时的性能稳定性,经常会使用到线程池来做多线程异步操作,多线程有2种,一种是实现runnable接口,这种没有返回值,一种是实现Callable接口,这种有返回值. 当其中一个线程超时的时候,理论上应该不 影响其他线程的执行结果,但是在项目中出现的问题表明一个线程阻塞,其他线程返回的接口都为空.其实是个很简单的问题,但是由于第一次碰到,还是想了一些时间的.很简单,就是因为阻塞的那个线 程没有释放,并发量一大,线程池数量就满了,所以其他线程都处于等待状态. 附上一段自己写的调

《创业家》牛文文:少谈点模式多谈点技术

"模式"如同当年的"主义",流行于各种创业大赛.创业励志节目.论坛的"街头"式秀场 文/创业家 牛文文 "美国某某公司你知道吧?就是刚被戴尔.惠普.思科十几亿美元抢购的那家.我们的模式和它的一样,现在还没赢利,可将来起码有十几亿人民币的市值." "我开了小煤矿,但煤运不出去,上商学院之后受到启发,想搞模式创新,具体讲就是想在铁路边上搞个煤炭物流开发区,建一个大的物流和信息流平台,把分散的煤炭集中在我这个园区,这样和铁

一起谈.NET技术,.NET 4 并行(多核)编程系列之一入门介绍

本系列文章将会对.NET 4中的并行编程技术(也称之为多核编程技术)以及应用作全面的介绍. 本篇文章的议题如下: 1. 并行编程和多线程编程的区别. 2. 并行编程技术的利弊 3. 何时采用并行编程 1.并行编程和多线程编程的区别. 1.1并行编程. 现在随着多核计算机的普及,并行编程技术,也就是多核编程技术也逐渐称为开发的主流.为此,在.NET 4 中就引入了"并行编程".在.NET 4 中一些列的Library和类为并行编程提供了支持,如: Task Parallel Librar

一起谈.NET技术,Silverlight的多线程能力(上)

对于多线程其实一直以来都存在很多误区:比如多任务与多线程就很容易被混为一谈,而多线程也常被理所应当的认为是并行等等.而事实却是:多任务≠多线程.单任务≠单线程.多线程不一定并行,多线程与性能不成线性关系等等,其中道理在这里不再详述.笔者认为Silverlight多线程主要作用不是在于提高性能,而是在于用户体验,其根本目的是解决用户体验中的响应速度,减少单线程带来的阻塞问题.用一个贴切的例子来形容单线程和多线程的区别:单线程就好像只有一个服务窗口卖票的车站,人们排队买票时都是单线程处理的,而且不能

一起谈.NET技术,用C#实现HTTP协议下的多线程文件传输

很多人都有过使用网络蚂蚁或网络快车软件下载互联网文件的经历,这些软件的使用可以大大加速互联网上文件的传输速度,减少文件传输的时间.这些软件为什么有如此大的魔力呢?其主要原因是这些软件都采用了多线程下载和断点续传技术.如果我们自己来编写一个类似这样的程序,也能够快速的在互联网上下载文件,那一定是非常愉快的事情.下面我就讲一讲如何利用C#语言编写一个支持多线程下载文件的程序,你会看到利用C#语言编写网络应程序是多么的容易,从中也能体会到C#语言中强大的网络功能. 首先介绍一下HTTP协议,HTTP亦

一起谈.NET技术,Silverlight 的多线程能力(下)

上一期笔者介绍了Silverlight实现多线程的诸多解决方案,本期笔者将通过一个实例来实现所有多线程编程方法,并且还将于JavaScript和Flash两种Web客户端技术性能进行比较,请勿拍砖. 在正式编程前,笔者还要重申上期非常重要的观点:Silverlight多线程主要作用不是在于提高性能,而是在于用户体验.这里要给多线程泼一盆冷水了,多线程与性能提升不是正比关系,如果你使用一个单核CPU的客户端设备,那么即便你创建100个多线程也与单线程的计算性能是一样的,因为一个CPU时间片下只能处

一起谈.NET技术,异步调用与多线程的区别

随着拥有多个硬线程CPU(超线程.双核)的普及,多线程和异步操作等并发程序设计方法也受到了更多的关注和讨论.本文主要是想探讨一下如何使用并发来最大化程序的性能. 多线程和异步操作的异同 多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性.甚至有些时候我们就认为多线程和异步操作是等同的概念.但是,多线程和异步操作还是有一些区别的.而这些区别造成了使用多线程和异步操作的时机的区别. 异步操作的本质 所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们

一起谈.NET技术,在.NET Workflow 3.5中使用多线程提高工作流性能

最近在工作上碰到一个性能问题,由于项目是基于SOA的架构,使得整个系统完全依赖于各种各样的Service,其中用于处理业务逻辑的Business Services全部都用.NET Workflow 3.5实现(历史原因,项目还没升级到Workflow 4).在众多的Business Service中,其中有一个的主要功能是,通过调用不同的Data Service来获取数据,然后根据业务逻辑来组织这些数据并返回给它的调用者.该Business Service的工作流(Workflow)主要包含三个

一起谈.NET技术,.NET多线程的探讨

本文开始总结.NET下的多种多线程机制,不断更新中,往各位补充.  Invoke机制 最近在实验一个webservice时候,想到了要用异步机制,于是好好研究了一下多线程和Invoke机制,这里写点小小的心得,如有不妥,请各位指教. 我们往往会遇到这样的需求:有一个十分耗时间的工作(比如一个WebSerive的请求),我们不希望它阻塞现有的UI线程(因为这样会导致界面假死),而是希望它在另外一个线程里面执行,并在执行完毕之后将结果"通知"UI线程.这个需求需要通过Invoke和委托