开启一个线程的方式:
方式一:Thread t1 = new Thread(Method_1);
t1.Start();
方式二:委托
Action ac = Method_1;
ac.BeginInvoke(null, null);
线程其实就是操作系统中提到更加小的运行单元,比如一个进程可以存在多个线程,线程的执行不一定按顺序,并且从外部看来是同时进行的。
我们举一个线程的一般定义,当然在定义之前需要先导入线程命名空间 using System.Threading;
class Demo1 { public void Method_1() { for (int i = 0; i < 100; i++) { Console.WriteLine("我是线程1"); } } public void Method_2() { for (int i = 0; i < 100; i++) { Console.WriteLine("我是线程2"); } } public void Test() { Thread t1 = new Thread(Method_1); t1.Start(); Thread t2 = new Thread(Method_2); t2.Start(); } static void Main(string[] args) { Demo1 obj = new Demo1(); obj.Test(); }
如果对于某一个线程比较简单,可以使用Lamda表达式
public void Test1() { Thread t1 = new Thread( () => { for (int i = 0; i < 100; i++) { Console.WriteLine("我是线程1"); } } ); t1.Start(); Thread t2 = new Thread( () => { for (int i = 0; i < 100; i++) { Console.WriteLine("我是线程2"); } } ); t2.Start(); } static void Main(string[] args) { Demo1 obj = new Demo1(); obj.Test1(); }
线程中的方法不止上文的,它本身有3个重载方法,接下来是线程传递一个参数的例子:
public void LoadDownFile(object fileName) { Console.WriteLine("文件名:"+fileName.ToString()); Console.WriteLine("文件下载:"+Thread.CurrentThread.ManagedThreadId); Thread.Sleep(1000); Console.WriteLine("下载完毕"); } public void Test2() { Thread t = new Thread(LoadDownFile); t.Start("abc.mov"); }
线程传递多个参数,在构造函数传递多个参数。
public class ThreadTest { private string _FilePath; private string _FileName; public ThreadTest(string filePath,string fileName) { _FilePath = filePath; _FileName = fileName; } public void DownLoadFile() { Console.WriteLine("开始下载"+_FileName+"//"+_FilePath); Thread.Sleep(3000); Console.WriteLine("下载完毕"); } }
public void Test3() { ThreadTest thObj = new ThreadTest("伤心的人别听慢歌","你呀你我说你什么好"); Thread t1 = new Thread(thObj.DownLoadFile); t1.Start(); }
委托开启线程,委托开启的线程是后台线程,需要加Console.ReadLine()要求主线程不关闭,知道后台线程运行完毕。
public void Test4() { Action ac = Method_1; ac.BeginInvoke(null, null); Console.ReadLine(); } public void Test5() { Action<int> ac = Method_3; ac.BeginInvoke(100, null, null); Console.ReadLine(); }
为了解决主线程不等待后台线程的情况,可以接收一个线程的返回值,进而判断其是否运行完成。
public int LoadMoreFile(int num) { Console.WriteLine("正在下载"); Thread.Sleep(1000); return num; } public void Test6() { Func<int, int> fu = LoadMoreFile;
#异步调用状态 IAsyncResult result = fu.BeginInvoke(100, null, null); while (!result.IsCompleted) { Console.Write("."); } int intResult = fu.EndInvoke(result); Console.WriteLine("线程返回的数值:"+intResult); Console.ReadLine();这里不需要加,因为主线程会等待后台线程结束后退出 }
使用回调函数实现线程异步:
public void Test7() { Console.WriteLine("使用回调函数的方式"); Func<int, int> fu = LoadMoreFile; fu.BeginInvoke(200, OnCallBack, fu); //主线程继续执行,当子线程结束自动回调,实现异步提高CPU效率 //.......... Console.ReadLine(); } //OnCallBack()是回调函数,当子线程结束时,自动调用 public void OnCallBack(IAsyncResult ar) { Func<int, int> res = ar.AsyncState as Func<int, int>; int intResult = res.EndInvoke(ar); Console.WriteLine("在回调函数中的结果:"+intResult); }
线程设置其中的优先级:5中优先级,Highest、AblowNormai、Normal、BelowNormal、Lowest。
public void Test() { Thread t1 = new Thread(Method_1); Thread t2 = new Thread(Method_2); Thread t3 = new Thread(Method_3); t1.Start(); t2.Start(); t3.Start(); t1.Priority = ThreadPriority.Highest; t2.Priority = ThreadPriority.BelowNormal; t3.Priority = ThreadPriority.Lowest; }
前台线程和后台线程:
前台线程:主线程和Thread构造的线程都是前台线程,前台线程可以修改为后台线程t.IsBackgound()
后台线程:比如之前通过委托构造的线程,Begin***为后台线程
需要注意一点的是:后台线程会随着前台线程的结束而关闭,也就说前台线程必须完成,而后台线程则会选择性关闭。
public void SleepTime() { Console.WriteLine("开始执行"); Thread.Sleep(3000); Console.WriteLine("执行完毕"); } public void Test2() { Thread t = new Thread(SleepTime); t.Start(); t.IsBackground = true; Console.ReadLine(); }