Loading

4:c#教程-多线程

4.1 多线程开发

线程与线程函数

把分割出来的工作任务封装为一个函数,由线程负责执行。线程的运行过程体现为线程函数的运行过程。

4.1.1 多线程开发基础知识

  • 线程对象的创建与运行
MyClass obj= new MyClass();
//原始写法
Thread th1 = new Thread(new ThreadStart(MyClass.StaticMethod)); //委托-静态方法
Thread th2 = new Thread(new ThreadStart(obj.InstanceMethod))// 委托-实例化方法

//简化写法
Thread th3 = new Thread(MyClass.StaticMethod);
Thread th4 = new Thread(obj.InstanceMethod);

//Lambda表达式
Thread th5 = new Thread(()=>{
    //线程函数
});
  • 多线程基本方法
th.start() // 执行线程
Thread.CurrentThread  //可获取负责执行当前函数的线程对象引用
Thread.ManagedThreadID // 每个线程都有一个ID
Thread.Sleep(number)  //当前线程暂停,进入阻塞状态,可能影响性能。number为时间,单位是毫秒
Thread.SpinSLeep(number) //让CPU空转,但线程状态不改变(不进入阻塞状态),只适合暂停很短时间时使用,小于1s
th.Abort()  //提前终止线程,一般不用
th.IsBackground  //设置属性为true的线程称为背景线程;背景线程在主线程结束时自动中断执行;默认为False,即“前台线程”,CLR会等待所有前台线程结束后才会结束整个线程。
th.Join()  //把线程嵌入到当值执行的线程中,当前线程会等待th线程执行完毕后再继续(需先th.start()),不推荐使用,容易造成死锁。Join就是插队的意思
//线程状态: 托管线程 不与 操作系统的原始线程 一一对应
  • 线程终止时,如何清理?
public void SomeLongTask(){
    try{
        System.Console.WriteLine("辅助线程开始。。。");
    }catch(ThreadAbortException e){  //需要捕获线程终止异常
        System.Console.WriteLine("辅助线程被提前终端:{0}",e.Message);
        Thread.ResetAbort(); //不加此句,CLR会再次抛出这个异常,从而导致函数最后函数最后一句代码不会执行
    }finally{
        System.Console.WriteLine("此时完成清理辅助线程占用的资源工作");
    }
    System.Console.WriteLine("辅助线程结束"); //不加 ResetAbort() 不会执行到此句
}

4.1.2 多线程开发基本技巧

public Thread(ThreadStart start);  //ThreadStart是委托,接收的函数不能有参数和返回值

如何接收带参数的线程函数?

  1. 外套函数(缺点:1.字段共有,违背面向对象的“封装”原则;2.如果有多个方法,则字段数目爆炸)
class MyThread{
    //带参数和返回值的函数
    public long SomeFunc(int xx, int yy){
        return xx + yy;
    }
    //将SomeFunc参数和返回值外化为类的共有字段
    public int x;
    public int y;
    public long returnValue;
    //供多线程调用的“外套”番薯
    public void ThreadMethod(){
        returnValue = SomeFunc(x,y);
    }
}

//使用时,先设置x,y的值,再调用线程,完成后获取returnValue
MyThread obj = new MyThread(){
    x = 100, y = 120
}
Thread th = new Thread(MyThread.ThreadMethod);
th.Start();
th.Join();
Console.WriteLine(obj.returnValue);
  1. 使用ParameterizedThreadStart委托(只接收一个object参数,需要创建参数辅助类ThreadMethodHelper)
//单参数无返回值时,直接改写函数
void Func(int x){
    //...
}
//==>
static void Func(object x){
    int argu = Convert.ToInt32(x);
    //...
}
Thread th = new Thread(new ParameterizedThreadStart(Func));
th.Start();

//多参数有返回值,使用参数辅助类
long SomeFunc(int x,int y ){
    long ret = 0;
    // ...
    return ret;
}
//==>
class ThreadMethodHelper{
    //线程输入参数
    public int x;
    public int y;
    //函数返回值
    public long returnValue;
}
public void SomeFunc(object argu){
    int x = (argu as ThreadMethodHelper).x;
    int y = (argu as ThreadMethodHelper).y;
    //...
    returnvalue = x +y ;
    (argu as ThreadMethodHelper).returnValue = returnvalue
}
//使用
var argu = new ThreadMethodHelper();
argu.x = 100; argu.y = 120;
Thread th = new Thread(new ParameterizedThreadStart(SomeFunc));
th.Start(argu);
th.Join();
Console.WriteLine(argu.returnValue); //取回线程结果

利用多线程回调

posted @ 2025-03-12 22:35  一起滚月球  阅读(15)  评论(0)    收藏  举报