C#线程处理
c#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个c#程序开始于一个单线程,这个单线程是被clr和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。
除非被指定,否则所有的例子都假定以下命名空间被引用了:
using system; using system.threading;
c#开启线程的方法有:
- 异步委托
- 通过thread类
- 线程池
- 任务
总的来说其实线程的开启基本都涉及到委托的使用。
一、异步委托开启线程
首先来看一个比较简单的例子,采用第一种开启线程的方法——异步委托
using system; using system.threading; namespace study { class program { static void test() { console.writeline("testthread"); } static void main(string[] args) { action a = test; a.begininvoke(null, null); console.writeline("mainthread"); console.readline(); } } }
编译运行,发现结果与预期有所不同。结果如下图
如果按着逐行运行代码的方式,那么应该是先输出testthread,但是结果却是先输出mainthread。
将a.begininvoke(null,null);
和console.writeline("mainthread");
对调位置之后,结果和之前的依然一致。这就说明,异步委托开启的线程是和主线程同时同步进行的。
action委托是指向一个没有返回值的函数,那么假设一个线程,我们需要取得他的返回结果并输出,那么就要用到func委托。
看下面的源码
using system; using system.threading; namespace summerstudy { class program { static string test(int i, string str) { console.writeline("testthread" + "\t参数i是:" + i); return str; } static void main(string[] args) { func<int, string, string> a = test; iasyncresult res = a.begininvoke(1, "返回值", null, null); string o = a.endinvoke(res); console.writeline("mainthread\t" + "线程返回值是:" + o); console.readline(); } }
同时异步委托开启线程中,判断线程是否结束的方法也有两种,一种是利用iasyncresult的iscompleted方法,一种是使用方法进行线程结束判断。
具体使用方法如下。
- iscompleted(bool)
iasyncresult ia = a.begininvoke() if(ia.iscompleted == false) { //goon }
- asyncwaithandle
iasyncresult ia = a.begininvoke() ia.asyncwaithandle.waitone(time);//time为等待时间,超时后才会运行下一行代码,未完成直接跳出返回false
或者通过自定义方法,begininvoke中倒数第二个参数是一个委托,传递一个函数,在线程结束之后会自动的调用。
static string test(int a) { } func<int, string> a = test; iasyncresult ia = a.begininvoke(100, callback, a); static void callback(iasyncresult ar) { func<int, string> a = ia.asyncstate as func<int, string>; string res = a.endinvoke(ar); }
在使用lambda表达式作为委托的时候,最后一个参数可以为空,因为lambda表达式可以访问外部变量。
二、使用thread类开启线程
使用thread类创建一个实例,它的构造方法中需要传递一个委托。通过委托绑定线程。
直接上代码
using system; using system.threading; namespace study { class program { static void test() { console.writeline("thread"); thread.sleep(2000); console.writeline("timeover"); } static void main(string[] args) { thread t = new thread(test); t.start(); console.writeline("main"); console.read(); } } }
对于需要传递参数的委托,则必须制定参数类型为object,在线程start方法中传递参数
namespace summerstudy { class program { static void test(object c) { int id = thread.currentthread.managedthreadid; console.writeline("thread,\t线程id为" + id + ",\t参数是:" + c); thread.sleep(2000); console.writeline("timeover"); } static void main(string[] args) { thread t = new thread(test); t.start("xxx.avi"); console.writeline("main"); console.read(); } } }
当然你也可以自定义一个类,在类中自定义数据传递。
三、线程池
这种方法有助于节省时间,具体使用方法如下
using system; using system.threading; namespace summerstudy { class program { static void test(object c) { int id = thread.currentthread.managedthreadid; console.writeline("thread,\t线程id为" + id + ",\t参数是:" + c); thread.sleep(2000); console.writeline("timeover"); } static void main(string[] args) { threadpool.queueuserworkitem(test, "asfasf"); console.read(); } } }
其中委托必须要有一个参数,无论是否使用该参数。且只适用于使用时间短的线程,不能改变优先级
四、任务
使用task类开启线程,还有taskfactory创建
task类实例
using system; using system.threading; using system.threading.tasks; namespace summerstudy { class program { static void test(object c) { int id = thread.currentthread.managedthreadid; console.writeline("thread,\t线程id为" + id); thread.sleep(2000); console.writeline("timeover"); } static void main(string[] args) { task t = new task(test, "asfgasg"); t.start(); //或者 taskfactory tf = new taskfactory(); task t1 = tf.startnew(test); console.read(); } } }
我的掘金:warrenryan
我的简书:warrenryan
欢迎关注我的博客获得第一时间更新
我的github:warrenryan
我的博客园:warrenryan
上一篇: .Net中XML,JSON的几种处理方式
下一篇: 真够艺术的