先抛开委托的各种写法说下,对于一个thread而言,你肯定是希望通过某种方式告知这个thread要做什么,这个要做的东西最终在c#中体现为一段代码或者方法。
基于上述结论,我们肯定是希望将这段代码或者方法带入到thread中去,带入的方法这块在java中看起来更纯粹些也更直观些
先构建一个对象实现Runnable,并实现其中的run方法,run方法最终会被某个线程来进行调用
class MyTask implements Runnable
{
@Override
public void run(){
//....we have a lot of work to do.
}
}
接下来告知一个线程,这个task你来执行
Thread td=new Thread(new MyTask(),"wtf");
td.start();
通过这种方式就告知了thread你要做什么,那么在c#中实际上最后编译后也就变成这个模样了。但在实际写代码的时候c#比java要更进了一步,因为在前面构建的那个myTask对象除了告知thread要执行啥外没什么球用了,如果仅仅是写一两个倒没什么很大问题,但一般而言一个项目中要用起来会发现java的这种写法相当啰嗦而且极为蛋疼,那么我们希望有种更简单明了的方法来进行描述。
假设我们希望thread执行的方法为
class Mywork{
public void LongRun(){.....}
pubic void LongRun2(int count){...}
}
最直接的方式肯定希望是直接把这个方法带到thread对象中去,比如
var thread=new Thread(new Mywork().LongRun());
但这个时候你会发现这个LongRun一旦这样写了后(忽略语法错误)其表达的意义就是要执行这个方法了(而不是延后到调用Start时执行),而我们只是希望在这一步告知thread后面Start的时候要执行什么,所以这种表述很直接的方式是有问题的。那么我们需要在这个基础上变动下,我们希望告诉thread要执行的方法是这个或者说要执行的方法在这里,既然直接的方式不行,那么我们就需要一个中间人来支持下。
你可以看下Thread的构造函数的重载中有一个Thread(ThreadStart start)的方法,这种ThreadStart就是中间人,也就是委托,我们需要他来承载一个方法或代码块,这样就能避免前面出现的new Thread(LongRun())这种尴尬的错误了。
接下来的事就是我们需要这个中间人出来干活了,那我们就直接把要做的事塞给ThreadStart这个中间人即可
ThreadStart threadStart=new ThreadStart(new Mywork().LongRun);
Thread thread=new Thread(threadStart);
这里和更前面那种写法就是一个小括号的差异,而这个差异却体现了委托和普通方法的差异之一。更前面那种方式一旦写了(假设能执行的话)一旦执行后就会变成先执行LongRun方法,然后再构建Thread对象,而后面这种方式则是通过ThreadStart这个委托间接的告知Thread对象当你后面要跑的时候需要执行Mywork#LongRun方法。
当你弄清楚这种写法后会发现这种和java那种又臭又长的没什么区别吧,所以在编译器层面玩了点花样,然后你就可以写成
#省略构造ThreadStart对象(编译后还是会有的,只是书写更简单)
Thread thread=new Thread(()=>{
new Mywork().LongRun();
});
#再省一点(省略return,因为委托方法原型推断出来为ThreadStart,而ThreadStart这个委托是无返回值的)
var thread=new Thread(()=>new Mywork().LongRun());
#继续省略(省略构建Mywork对象,我们只是需要一段代码块而已,Mywork对象存在纯属多余)
var thread=new Thread(()=>{
//...long run work here
//...Thread.Sleep(1000);
});
到了这里c#相对java的语法/语法糖优势就充分体现出来了,当然这里不是说语法优势,只是通过java的语法告诉你其中的整个演变过程。
回到前面,我们将LongRun方法作为目标方法交给委托对象ThreadStart,那么你可以看下是否可以将Mywork#LongRun2方法也交给ThreadStart方法呢?
谢谢你。
ThreadStart threadStart=new ThreadStart(new Mywork().LongRun);
我不明白为什么要用new Mywork ? 用Mywork不好吗?
就好比书中的Thread myThread = new Thread(new ThreadStart(myTask));
为什么ThreadStart 前面要加个new? 直接用ThreadStart 不好吗?
只能说你对委托的认识不够,你的据我所知是对的,只不过你没转过弯,在这里,委托是系统已经定义好了,你只是调用而已。
我知道委托是可以调用的,在这里创建线程的过程中,调用了任意一个委托,作为了新线程的参数,对吧?
而书中解释的是方法的名称应该不对,()里面的是参数,而不是方法。
1.委托的定义
1.1从数据结构来讲,委托和类一样是用户自定义类型
1.2从设计模式来讲,委托提供了方法的抽象。
1.3委托是类型,就好像类是类型一样。与类一样,委托类型必须在被用来创建变量以及类型对象之前声明。
有些东西不要光看书,写个demo,打断点跟进看看源码更好
这里的“委托”是指委托类型的变量,myTask
只是一个变量名而已
勇哥:
ThreadStart threadStart=new ThreadStart(new Mywork().LongRun);
我不明白为什么要用new Mywork ? 用Mywork不好吗?
就好比书中的Thread myThread = new Thread(new ThreadStart(myTask));
为什么ThreadStart 前面要加个new? 直接用ThreadStart 不好吗?
@绿绿山水: Mywork与ThreadStart是类,new出来的是对象
新版的c#里有匿名委托,泛型委托,都不需要显式声明delegate关键字啦。
还有豆不?
选为最佳答案是有5个豆的。