.NET : 多线程面面观
在.NET程序中,你需要了解多线程的知识包括如下几点
1. 什么是多线程
线程是目前程序可以直接控制的一个单元。我们的程序是运行在下面这样的一个环境中的
操作系统==>进程(Process)==>应用程序域(AppDomain)
通常情况下,一个.NET程序集(尤其是exe),默认还是有一个独立的进程。然后在这个进程中,会至少有一个应用程序域(AppDomain),这种新的机制是可以更好地提供程序集的安全性。
我们的代码需要在所谓的线程上运行。而一个程序至少会有一个线程。
如果我们需要,我们当然可以出创建多个线程。
2. 为什么要多线程
多线程,主要是因为我们想提高程序的可伸缩性。例如,我们有很多任务需要并行进行,那么我们可能需要多线程。
3. 怎么理解多线程
通常,我喜欢比较所谓的同步和异步。同步(所有任务在单个线程中依次排队执行),相当于单车道。而异步,则相当于多车道。从这个意义上讲,多车道当然提高了车辆通行的流量。当然,也正因为如此,多线程并不是免费的午餐。它肯定有成本,因为多个车道之间转换和同步是相对来说比较复杂的。
4. 线程是不是越多越好
不是!多线程虽然看起来是多车道,但其实那是我们一个比较形象的比喻而已。除非你真的拥有多个CPU,那么多线程实际上是一个假象,就是说,因为CPU的时间总是有限的,那么CPU需要频繁地切换,在某个时间执行某个线程的任务。这种情况,如果用的不好,反而增加了CPU的负担,降低了系统性能。
而且,多线程操作需要你有更好的专业知识,包括线程之间的安全性,同步,切换等等。
5. 三种操作多线程的方法
- 直接创建Thread对象,并且调用它的Start方法(更有操控力)
- 使用ThreadPool.QueueUserWorkItem方法(更有安全性)
- 使用.NET 2.0提供的BackgroundWorker(更方便)
下面来看一个例子
例如,我们有下面这样一个方法,需要单独开一个线程去工作
static void SomeMethod(object max)
{
int length = (int)max;
for (int i = 0; i < length; i++)
{
Console.WriteLine(i.ToString());
}
}
这个方法很简单,根据一个传入的参数,做一个循环
下面来看,如何使用上面三种方法实现多线程
直接使用Thread对象
Thread thread = new Thread(new ParameterizedThreadStart(SomeMethod));
thread.Start(100);
使用ThreadPool对象
ThreadPool.QueueUserWorkItem(new WaitCallback(SomeMethod), 100);
使用BackgroundWorker
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync();
static void worker_DoWork(object sender, DoWorkEventArgs e)
{
SomeMethod(100);
}
本文完整代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.ComponentModel;
namespace ConsoleApplication1
{
/// <summary>
/// 多线程的范例
/// 作者:陈希章
/// </summary>
class Program
{
static void Main(string[] args)
{
//使用Thread对象
Thread thread = new Thread(new ParameterizedThreadStart(SomeMethod));
thread.Start(100);
//使用ThreadPool对象
ThreadPool.QueueUserWorkItem(new WaitCallback(SomeMethod), 100);
//使用BackgroundWorker对象
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync();
Console.Read();
}
static void worker_DoWork(object sender, DoWorkEventArgs e)
{
SomeMethod(100);
}
static void SomeMethod(object max)
{
int length = (int)max;
for (int i = 0; i < length; i++)
{
Console.WriteLine(i.ToString());
}
}
}
}