C#高级学习第五章线程,任务和同步

xiaoxiao2021-02-28  16

进程和线程:

CPU总是运行一个进程,其他进程处于非运行状态,一个进程可以包含多个线程,每个线程可以使用进程的共享空间

互斥锁:防止多个线程同时读写某一块内存区域

信号量:用来保证多个线程不会互相冲突

一个线程里的语句是从上到下的,多线程编程是同步的,看里头代码的消耗时间

1.委托方式发起线程:(开始线程的4种方法)

static int Test(int i,string str)       一般我们会为比较耗时的操作 开启单独的线程去执行,比如下载操作 

{

   Debug.Log("test"+i+str);

   Thread.Sleep(100);   让当前线程休眠(暂停线程的执行)  单位ms   using System.Threading

   return 100;

}

1.通过委托开启一个线程

Func<int,string,int> a=Test;

IAsyncResult ar=a.BeginInvoke(100,"siki",null,null); 开启一个新的线程去执行 a所引用的方法

//IAsyncResult 可以取得当前线程的状态

可以认为线程是同步执行的(异步执行)

Debug.Log("main");

While(ar.IsCompleted==false)  如果线程没有执行完毕

{

   Debug.Log(".");

   Thread.Sleep(10);

}

int res=a.EndInvoke(ar); 取得异步线程的返回值

Debug.Log(res);

(2)检测线程结束

Bool isEnd=ar.AsyncWaitHandle.WaitOne(1000);  1000毫秒表示超时时间,如果等待了1000毫秒线程还没有结束的话,那这个方法返回false,如果在1000毫秒内线程结束了,那这个方法返回true;

if(IsEnd)

{

   int res=a.EndInvoke(ar);

  Debug.Log(res);

}

 (3)用回调函数检测线程结束

Func<int,string,int> a=Test;

倒数第二个参数是一个委托类型的参数,表示回调函数,就是当线程结束的时候会调用这个委托指向的方法,倒数第一个参数用来给回调函数传递数据

a.BeginInvoke(10,"siki",ar=>

{

    int res=a.EndInvoke(ar);

    Debug.Log(res+"在Lambda表达式取得");

},null);

2.使用Thread类可以创建和控制线程,Thread构造函数的参数是一个无参无返回值的委托类型

using System.Threading

Thread t=new Thread(()=>    创建一个线程

{

    Debug.Log("开始下载"+Thread.CurrentThread.ManagedThreadId);  获得当前线程的ID

    Thread.Sleep(2000);

    Debug.Log("完成下载");

});

t.Start();   开始去执行线程

(2)也可以传一个方法DownloadFile  (传递一个参数)

static void DownloadFile(object filename)

{

   Debug.Log("开始下载"+Thread.CurrentThread.ManagedThreadId+filename);

   Thread.Sleep(2000);

   Debug.Log("完成下载");

}

Thread t=new Thread(DownloadFile);

t.Start("xxx.bt");

第二种传递参数的方法,建立一个Thread类

Public class MyThread

{

    private string filename;

    private string filepath;

    MyThread(string filename,string filepath)

  {

       this.filename=filename;

       this.filepath=filepath;

  }

  public void DownFile()

  {

   Debug.Log("开始下载"+filename+filepath);

   Thread.Sleep(2000);

   Debug.Log("完成下载");

  }

}

MyThread my=new MyThread("xxx.bt","http:\\www.xxx.com");

Thread t=new Thread(my.DownFile) 我们构造一个thread对象的时候,可以传递一个静态方法,也可以传递一个对象的普通方法

t.Start();

前台线程和后台线程:

 只有一个前台线程在运行,应用程序的进程就在运行,判断前台线程是否结束决定程序是否在运行

用Thread类创建的线程是前台线程,线程池中的线程总是后台线程

Thread t=new Thread();

t.IsBackground(true); 把前台线程变成后台线程

t.Abort() 停止线程方法,会抛出一个ThreadAbortException类型的异常

3.线程池

适合于时间较短的任务,如果进程的所有前台线程都结束了,所有的后台线程就会停止

ThreadPool.QueneUserWorkItem(ThreadMethod);   开启一个工作线程

线程池所有线程都是后台线程,不能修改成前台线程,也不能修改线程池优先级或名称

4.任务:Task

Task t=new Task(ThreadMethod);  传递一个需要线程去执行的方法

t.Start();

第二种方法:

TaskFactory tf=new TaskFactory();  开启任务

Task t=tf.StartNew(ThreadMethod);

连续任务:

Task t1=new Task(doFirst);

Task t2=t1.ContinueWith(doSecond);

Task t3=t1.ContinueWith(doSecond);

Task t4=t2.ContinueWith(doSecond);

解决争用问题:(多个线程进行)

Lock(m) 向系统申请可不可以 锁定m对象,如果m对象没有被锁定,那么可以 如果m对象被锁定了,那么这个语句就会暂停,知道申请到m对象

{

 m.ChangeState(); 在同一时刻,只有一个线程在执行这个方法

}  释放对m的锁定

转载请注明原文地址: https://www.6miu.com/read-1950157.html

最新回复(0)