作为C#中较为高级的概念,线程的使用常常给开发人员,尤其是初级程序员带来不少的困惑。下面就来谈谈一些关于在Winform中使用线程的话题,在正式开始之前,我认为很有必要弄清楚一些基本概念和一些区别。
什么是线程?
也许一来就搬出一堆概念来,会让人反感,那么就从线程和进程的关系说起吧。
在早期的多任务操作系统中,并没有独立的线程概念,只有进程概念。为了使多个任务互不干扰的运行,没个进程都拥有独立的虚拟地址空间、代码段、数据段及堆栈等,除此之外,进程还占有了各种系统资源(例如文件、窗体对象、环境变量等等)。开始执行一个程序即创建了一个进程,进程拥有自身独立的资源,进程之间相互隔离、互不干扰。而后线程出现了。多个线程作为独立的执行单元可以存在于同一个进程中。线程共享其所属进程拥有的资源,可以访问进程的内存区域和代码段,而且线程还拥有各自的局部变量和对立的栈空间。
线程出现后,进程就作为程序运行所需公共资源的管理单元,而线程则作为程序的可执行单元,成为了任务调度的基本单元。
上一段的斜线部分,便可作为线程的基本概念来理解,不过我简单归纳一下,线程其实就是程序中单一的顺序控制流程。
进程与线程的区别
通常一个程序需要同时执行多个不同的任务,由于这些任务是属于同一个程序,通常没有必要利用进程所具有的严格的资源管理方式为每个任务分配独立的资源。由于进程之间的完全隔离性,在多任务进行切换时,进程的开销也较大。而线程共享进程中的资源,仅仅有少量的数据需要在线程之间进行隔离。创建一个线所需要的资源要远远小于创建进程。显然,线程之间通信的效率要高于进程之间的效率。
说了那么多,现在该是使用线程的时候了。首先先让我们通过几个小程序来热热身。
例1:
:
Thread myThread = new Thread( new
ThreadStart(myFunc) );
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
要运行线程我们首先我们要写
:
Thread t1 = new Thread( new
ThreadStart(Incrementer) );
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
t1.Start()
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
详细的代码如下
输出:
阻塞线程
阻塞调用线程,直到某个线程终止时为止
例: 线程挂起
在某些情况下我们需要将某些正在运行中的程序挂起.
例 线程的高级使用
异步调用
例2
namespace
Programming_CSharp
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
using System;
using System.Threading;
class Test
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
static void Main( )
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
// 生成一个本类的实例
Tester t = new Tester( );
t.DoTest( );
}
public void DoTest( )
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
//给Incrementer开一个线程并传入ThreadStart代理
Thread t1 =new Thread(new ThreadStart(Incrementer) );
//给Decrementer开一个线程并传入ThreadStart代理
Thread t2 =new Thread(new ThreadStart(Decrementer) );
// 线程开始
t1.Start( );
t2.Start( );
}
public void Incrementer( )
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
for (int i =0;i<1000;i++)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
Console.WriteLine("增加: {0}", i);
}
}
public void Decrementer( )
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
for (int i = 1000;i>=0;i--)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
Console.WriteLine("减少: {0}", i);
}
}
}
}
增加: 102
增加:
103
增加:
104
增加:
105
增加:
106
减少:
1000
减少:
999
减少:
998
减少:
997
t2.Join( )
t2.Sleep(毫秒数)
输出:
namespace
Programming_CSharp
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
using System;
using System.Threading;
class Test
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
private int counter = 0;
static void Main( )
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
//生成一个本类的实例
Tester t = new Tester( );
t.DoTest( );
}
public void DoTest( )
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
Thread t1 = new Thread( new ThreadStart(Incrementer) );
t1.IsBackground=true;
t1.Name = "线程1";
t1.Start( );
Console.WriteLine("开始线程 {0}",
t1.Name);
Thread t2 = new Thread( new ThreadStart(Incrementer) );
t2.IsBackground=true;
t2.Name = "ThreadTwo";
t2.Start( );
Console.WriteLine("开始线程 {0}",
t2.Name);
t1.Join( );
t2.Join( );
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Console.WriteLine("所有线程完成.");
}
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
public void Incrementer( )
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
try
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
while (counter < 1000)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
int temp = counter;
temp++; // 增加
Thread.Sleep(1);
counter = temp;
Console.WriteLine("线程 {0}. 增加: {1}",Thread.CurrentThread.Name,counter);
}
}
catch (ThreadInterruptedException)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
Console.WriteLine("线程 {0} 中断! 清空中…",Thread.CurrentThread.Name);
}
finally
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f2671b7f42ce505d9bf55a7a0ca257fb.gif)
{
Console.WriteLine("线程 {0} 退出. ",Thread.CurrentThread.Name);
}
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
线程开始线程1
线程开始 线程1
线程 线程1. 增加: 1
线程 线程1. 增加:
2
线程 线程1. 增加:
3
线程 线程1. 增加:
3
线程 线程1. 增加:
4
线程 线程1. 增加:
4
线程 线程1. 增加:
5
线程 线程1. 增加:
5
线程 线程1. 增加:
6
线程 线程1. 增加:
6
前面写的这些比较基础,主要是为了明确一些概念,熟悉常用的方法,方便从相关的源代码进行进一步学习,之后还会发一些线程高级应用的文章和一些例程。