成都网站建设
|
域名注册
|
虚拟主机
|
网站制作
|
网站案例
|
网站优化
|
网站推广
|
企业邮局
|
服务器租用
|
广告设计
首页
服务器租用
企业邮箱
虚拟主机
网站程序
营销推广
网站建设
域名注册
前端开发
网站备案
网站程序
java教程
asp程序
asp.net程序
vb编程
php程序
C#程序
服务器租用
web服务器
FTP服务器
服务器托管
服务器租用
vps主机服务器
云主机服务器
网站解决方案
服务器机房
企业邮箱
企业邮箱设置
企业邮箱优势
邮箱其他问题
邮箱功能讲解
邮箱收发问题
虚拟主机
主机管理
主机购买
数据库
主机续费升级
FTP上传
营销推广
seo优化
网站推广
搜索引擎
免费资源
网站建设
网站方案
网站改版
网页设计
网站维护
网站策划
网站制作
域名注册
域名转入\转出
英文域名
通用网址
中文域名
域名解析
无线网址
域名知识及服务
前端开发
html
jQuery
JavaScript教程
css
div+css
json教程
bootstrap教程
XML教程
ajax教程
网站备案
备案资料下载
备案流程指南
各省备案要求
备案常见问题
移动互联网
app应用开发
wap手机网站
微网站
当前位置:
创新互联
>>
常见问题
>>
网站程序
>>
C#程序
>>
初识C#线程
初识C#线程
作者:创新互联 文章来源:网站程序部 点击数:
更新时间:2008-11-10
使用多线程技术能有效地帮助你实现应用程序的更高性能和更优良的可伸缩性。但在真正运用这项技术的时候务必小心。本文是对线程技术所牵扯的工具和技术问题系列文章的开篇。我首先对线程概念进行介绍,然后总结一些常用的构造,最后介绍它们的用法。
线程的两面性
用
Java
语言编写多线程程序并不难,这是好事也是坏事。微软在开发
C#
时,他们把这种易用性的窘境全盘照搬到了整个新平台上。同时,C#相比Java具有更多的程序原语,但是Thread对象和同步监视器的基本Java原语从形式和功能上看都已足够提供强大的线程编程能力了。因此,在决定为应用程序采用多线程技术之前务必小心。
为什么不用多线程
首先得记住,在决定是否采用多线程技术时,除非你正在玩代码,否则千万别因为多线程编程够“酷”而简单地使用线程技术编程。多线程编程技术太时髦了,如果你不小心点你的老板迟早也会着迷,那时你就死定了。其次,不要因为让程序运行得更快而轻易采用多线程,除非你真的能证明单线程实现确实慢得可以。最后,在冒昧地一头扎进多线程机制之前,先回忆下微软所提供的一种公寓(apartment)模型,也就是把对象写成单线程构造而运行在多线程环境下。所以,说来说去,你并不一定非要采用多线程编码。不过,公寓模型是另外一个话题了。
如果做得不对,多线程编程势必会打开“潘朵拉的盒子”(意思是说惹出无数的麻烦)。重复性不明显、产生程序垃圾、记数器没有正确增值等等。你的应用程序还可能突然挂起。例如,数据库连接这类资源就可能出人意料地关闭或者变得过载。高级开发人员所面临的一个大麻烦就是解决线程问题。这些大问题不花点时间休想解决,而且它们对产品交货日期以及产品可靠性产生了严重的负面影响。
为什么要用多线程
如果你的应用程序需要采取以下的操作,那么你尽可在编程的时候考虑多线程机制:
连续的操作,需要花费忍无可忍的过长时间才可能完成
并行计算
为了等待网络、文件系统、用户或其他I/O响应而耗费大量的执行时间
所以说,在动手之前,先保证自己的应用程序中是否出现了以上3种情形。
如果你的代码运行得足够快,但是你认为你能让它运行得更快(假设你确实有这本事),我劝你最好不要接受这种诱惑。如果你不能肯定程序的计算操作并行性(例如针对同一数据表的并发数据库更改——当你的
数据库
达到了数据表级锁定的情况下),那么再想想其他法子吧。还有,如果你不知道应用程序是否因为等待输入或输出而花费了过多的时间,那么请首先搞清楚真正耗费时间的情况再说。实际上,启动3个线程以百万分之一的步长计算圆周率所消耗的时间就比同一线程重复计算3次要长得多。为什么会出现这种失败的情形呢?原因就在于,虽然第2条并行计算确实可用,但设计者却恰恰忽略了以上第3个标准:并行计算可以用到的一次计算期间却没有空闲周期。
假如你在为一台装备了多个处理器的并行计算机编写程序,则以上规则在这种情况下例外,你可以通过适当的并行操作设计而令软件性能大大获益——哪怕每一操作都对CPU时间极其贪婪。
基本的线程管理工具
刚才我已经为多线程编程提出了相当程度的警告,同时还为何时使用或者不使用多线程提出了建议,接下来我对多线程编程所能利用的某些工具进行阐述。
Thread对象
.NET库提供了一种名为System.Threading.Thread的对象,这种对象代表了单一线程。你可以启动线程、在当前线程继续运行的情况下设法完成线程的任务。这对那些需要打印文档或者保存大型文件但希望获得用户确认请求并给用户返回控制的应用程序来说帮助实在太大了。我们通过程序清单A演示了这一机制。
程序清单A
using System;
using System.Threading;
namespace Threads1 {
class Listing1 {
static void SayHello() {
Console.WriteLine("Hello, ");
Thread.Sleep(750 /*mSec */);
Console.WriteLine("World");
}
static void Main(string[] args) {
Thread t1 = new Thread(new ThreadStartSayHello));
t1.Start();
Console.WriteLine("Thread started. Main done.");
}
}
}
我们首先创建了一种方法:SayHello,由它完成我们的任务——显示问候语。它的签名必须匹System.Threading.ThreadStart指派(delegate)。注意,SayHello 方法调用了Thread.Sleep(int numMillisecs)方法。这是一种相当有用的构造而且会经常出现在这类示例中。
在主程序中,我们通过带SayHello方法的ThreadStart指派创建了一个新线程,并在该线程上调用Start方法。我们创建的线程随之被启动,然后我们的主线程在这个例子中继续运行到结束。
在很多情况下你可能要在各个线程中分别执行存在轻微差别的任务,同时需要把某种参数从一种任务所在的线程传递给另一任务所在的线程。要完成这一目标可以采取好几种合理的方式,最直接的做法就是创建一种Task对象,由它保存线程、特有的参数以及提供ThreadStart指派的worker方法。利用worker方法即可读取所提供的参数,因为它正好就是Task对象的成员所以对线程当然是唯一的。通过令线程成为一种公共字段,你就可以获得访问线程所有成员的权限而不必编写额外的封装代码了。请参看程序清单B 阅读这一技术的有关示例。
程序清单B
using System;
using System.Threading;
namespace TaskDemo {
public class MyTask {
public Thread m_thread;
string m_name;
public MyTask(string name) {
m_name = name;
m_thread = new Thread(new ThreadStart(Worker));
}
private void Worker() {
Console.WriteLine("Hello, ");
Thread.Sleep(1500);
Console.WriteLine(m_name);
}
}
class TaskDemo1 {
static void Main(string [] args) {
MyTask task1 = new MyTask("Bill");
MyTask task2 = new MyTask("Steve");
task1.m_thread.Start();
task2.m_thread.Start();
}
}
}
你甚至可以通过在保存线程的任务中定义字段的方法提供Task对象的某种返回值,在线程完成前设置这一返回值,最后在这项任务完成以后从启动这项任务的线程读取它。
你可以暂停一个线程、等待其他线程完成其任务。你可以在打算采集返回结果的时候执行两种操作,在三个分隔的线程之间执行数据库更新但直到所有线程都结束时才想进行数据处理也可以采用以上两种操作。该技术如程序清单C所示。
程序清单C:
http://builder.com.com/utils/sidebar.jhtml?id=u00220020531pcb01.htm&index=3
这里,我们采用了程序清单A的代码创建程序。这次我们运行两个线程,每一个线程完成同以前一样的任务。调用两个线程的Start () 方法之后调用它们的Join()方法。对线程调用Join()方法会令调用线程暂停执行直到被调用线程结束。因此thread1.Start ()方法会令主线程暂停直到thread1完成。然后我们对thread2执行同样的操作。结果,主线程直到thread1和 thread2都完成了才最后完成。
这个例子的思想分为两部分。首先,某一个线程不能调用另一线程上的Join方法除非后者已经启动。第二,有多于两种形式的Join可以设定调用线程继续运行的超时时间哪怕被调用线程仍在运行。
计算机科学中经常会提到看门狗概念,所谓看门狗(watchdog)其实就是负责保证功能正确性或者处理不正确功能的实体。另一种实体,也就是常用的看门狗计时器(watchdog timer)则通常负责保证另一任务在合理的时间内按时完成。程序清单D所示就是实现看门狗计时器的简单实现机制。
程序清单D:
http://builder.com.com/utils/sidebar.jhtml?id=u00220020531pcb01.htm&index=4
thread1启动之后我们就加入该线程但提供了10秒钟的超时时间。因为thread1内置15秒暂停设置,所以在加入
C#中实现窗体间传值
:上一篇
C#中ref和out的使用小结
:下一篇
C#程序相关文章
C#中实现窗体间传值
C#必备知识之预编译指令
C#如何获取机器上正在运行的进程?
C#淡出淡入窗体
C#递归删除文件夹目录及文件的方法
C#连接数据库和更新数据库
C#定义常量的两种方法
C# 4.0 的4个新特性
C++程序员容易犯的十个C#错误
你知道C#排序的编写及性能吗?
专注网站建设、网页设计、网站制作、企业网站建设——创新互联
服务电话:028-86922220 13518219792 公司地址:成都市太升南路288号锦天国际A幢10楼2号
企业邮箱:
service@cdxwcx.com
版权所有:成都创新互联科技有限公司 蜀ICP备13010860号
成都网站建设