c# 线程
简介:这一篇我们主要学习线程及相关示例。
C# Threading
何谓线程,即并行工作或代码执行。为了同步执行多任务则意味着threading。
例如在电脑桌面,开启微软的PPT和Excel就是线程。一个程序经常会以两种方式被执行:同步或异步的方式。
同步则意味者多个工作是一个接一个的被执行。下图的work 2就必须等到work 1完成后才能开始。
异步则可以在同一时间执行多个工作。
MSexcel跟PPT的异步执行是一个最常见的线程示例。系统为每一个开启的应用程序生成了对应的新线程,因此每一个线程有一个独立的执行通道去异步执行对应的应用。
C#在Console Application,WindowsForm,WPF中广泛支持线程threading,所以我们可以在一个console app里面创建新线程,这意味着我们可以创造一个多线程环境。
用示例手把手教你C#线程
这里使用VS2017,其它版本操作大致类似.
为了在工程中创建新线程,我们需要导入线程的命名空间System.Threading,这能帮助建立多线程应用。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { class Program { static void Main(string[] args) { Thread th = Thread.CurrentThread; } } }
如你所见,没有添加threading线程命名空间,便无法使用thread类。 添加后,便可正常运行。
现在为了更好的进一步理解,我们会新建两个方法,work1和work2 ,在各自内容中会添加一个for循环,然后可以观察各自的运行情况:
class Program { static void Main(string[] args) { Work1(); Work2(); Console.ReadLine(); } static void Work1() { for (int i = 1; i <= 10; i++) { Console.WriteLine("Work 1 is called " + i.ToString()); } } static void Work2() { for (int i = 1; i <= 10; i++) { Console.WriteLine("Work 2 is called " + i.ToString()); } } }
如你所见,我们建了两个普通的功能函数,执行后下面是输出:
看完输出你会发现,当两个函数同步运行时(work2紧接着work1),work2必须等到work1的循环完成后才会开始运行。
但考虑到现代社会习惯的多任务同步执行,在实际运用中,我们需要另一种机制来同时执行work1和work2。因此我们把这种机制叫做Threading。
下面我们就会看到threading是如何解决两个功能函数同时运行的问题。
第一步
添加命名空间。
using System; using System.Threading;
第二步
在main函数中创建线程对象。
static void Main(string[] args) { Thread oThreadone = new Thread(Work1); Thread oThreadtwo = new Thread(Work2); Console.ReadLine(); }
第三步
调用线程对象。
static void Main(string[] args) { Thread oThreadone = new Thread(Work1); Thread oThreadtwo = new Thread(Work2); oThreadone.Start(); oThreadtwo.Start(); Console.ReadLine(); }
调用成功后,我们来看一下输出:
可以看到work2是跟work1同时执行的。为了使得输出效果更明显,你可以在work1及work2中加一点延时,这样你可以看到每一次延时后,两个work同步输出的内容。
由上可证,我们可以采用异步的方法同时执行多个任务。
为了创建线程类的应用,还有一些常用且比较重要的方法。
- 1 : Thread Join
- 2 : Thread Sleep
- 3 : Thread Abort
Thread join的使用
Thread.Join() 使线程完成工作或直到该线程完工后让另一线程停止。join方法使其可以附加到任意线程,它会先执行那个线程然后使其它停止。如果文字比较难懂,那么可以先看看join的示例把。
class Program { static void Main(string[] args) { Thread oThread = new Thread(MethodJoin); oThread.Start(); oThread.Join(); Console.WriteLine("work completed..!"); Console.ReadLine(); } static void MethodJoin() { for (int i = 0; i <= 10; i++) { Console.WriteLine("work is in progress..!"); } } }
如你所见,这里我建了一个新的方法MethodJoin(),并用join将他附加到oThread上。
如图你可以看到MethodJoin里所有的内容都已执行完,然后才回到main中做剩下的工作。
Thread Sleep的使用
顾名思义,sleep可以使得线程延迟一个特定的时间。在sleep模式下,cpu不会消耗任何资源。
接下来的一个例子,我会使得一个线程停留4s,然后输出一些内容,总共6次。为了计算准确,这里加入了.net Diagnostics 命名空间,可以使用码表以及执行时间。
using System.Threading; using System.Diagnostics; using System; class Program { static void Main(string[] args) { Stopwatch stWatch = new Stopwatch(); stWatch.Start(); Thread oThread = new Thread(ProcessSleep); oThread.Start(); oThread.Join(); stWatch.Stop(); TimeSpan ts = stWatch.Elapsed; string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds); Console.WriteLine("TotalTime " + elapsedTime); Console.WriteLine("work completed..!"); Console.ReadLine(); } static void ProcessSleep() { for (int i = 0; i <= 5; i++) { Console.WriteLine("work is in progress..!"); Thread.Sleep(4000); } } }
如图,在ProcessSleep中加入了一个4s的延时,下面是输出的内容:
Thread Abort的使用
如名,abort就是结束或终止进程,在停止进程中,它会触发ThreadAbortException。
Thread objThread = new Thread(ProcessJoin); objThread.Start(); objThread.Join(); objThread.Abort();
c#中 线程的类型
前台线程Foreground Thread
如你所知Main函数本身是一个独立线程,所以在main里面加入一个线程则意味者这将成为一个多线程应用。前端线程Foreground 可以一直执行完毕即使主线程终止。用例子来解释foregound的生命周期不依赖主线程:
class Program { static void Main(string[] args) { Thread oThread = new Thread(WorkThread); oThread.Start(); Console.WriteLine("Main Thread Quits..!"); } static void WorkThread() { for (int i = 0; i <= 4; i++) { Console.WriteLine("Worker Thread is in progress..!"); Thread.Sleep(2000); } Console.WriteLine("Worker Thread Quits..!"); } }
从上图可以看出,即使main已经终止,workthread仍然持续在输出。
后台线程Background Thread
后台线程与前台线程的机制刚刚相反,即当主线程终止时,后台线程也终止。为了运行后台线程,我们需要将IsBackground的属性设置为true。
Thread oThread = new Thread(WorkThread); oThread.IsBackground = true;
using System.Threading; using System.Diagnostics; using System; class Program { static void Main(string[] args) { Thread oThread = new Thread(WorkThread) { IsBackground = true }; oThread.Start(); Console.WriteLine("Main Thread Quits..!"); } static void WorkThread() { for (int i = 0; i <= 4; i++) { Console.WriteLine("Worker Thread is in progress..!"); Thread.Sleep(2000); } Console.WriteLine("Worker Thread Quits..!"); } }
执行后,会发现开始后很快程序便结束,没有执行workthread内的内容;而前台线程会执行完所有内容。
好了,线程的基本内容就这样了,如果想更深入的了解,就得靠动手了!
参考:
1, https://www.tutorialspoint.com/csharp/csharp_multithreading.htm
2, http://www.learncsharptutorial.com/threading-and-types-of-threading-stepbystep.php