欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.net 多线程 Thread ThreadPool Task

程序员文章站 2022-04-20 21:10:37
先准备一个耗时方法 /// /// 耗时方法/// /// private void DoSomeThing(string name){ Console.WriteLine($"开始执行{name}, {Th ......
先准备一个耗时方法
/// <summary>
/// 耗时方法
/// </summary>
/// <param name="name"></param>
private void dosomething(string name)
{
                 console.writeline($"开始执行{name}, {thread.currentthread.managedthreadid.tostring("00")} ,{datetime.now}");
                 int num = 1;

                 for (int i = 0; i < 100000000; i++)
                 {
                                 num++;
                 }
                 thread.sleep(1000);

              console.writeline($"结束执行{name}, {thread.currentthread.managedthreadid.tostring("00")} ,{datetime.now},{num}");
}
 
 
.net framework框架1.0和1.1时期,多线程,用thread
 
threadstart  threadstart = new threadstart(()=>this.dosomething("thread"));
thread thread = new thread(threadstart);
thread.start();// 开始执行多线程任务了。
 
//thread.start();默认是前台线程,ui退出后,还是会继续执行完,如果thread.isbackgroud=true;//就变成主线程关闭就直接关闭了
 
thread.join();//这个方法是让主线程等着当前线程完成之后再执行
 
thread.suspend();//暂停  过时方法不推荐
thread.resume();//重启  过时方法不推荐
thread.abort();//销毁  过时方法不推荐
 
基于thread封装一个支持回调
private void threadwithcallback(threadstart threadstart  action callback)
{
          threadstart  startnew = new threadstart(
                  ()=>
                     {
                             threadstart.invoke();//执行传入的线程方法
                             callback.invoke(); //执行回调函数
                     } 
             );
          thread thread = new thread(startnew);
           thread.start();
}
 
调用这个方法:
threadstart threadstart = new threadstart(() => this.dosomething("thread"));
 action callback = () => console.writeline("这是回调函数");
 
this.threadwithcallback(threadstart , callback );
 
 
/// <summary>
/// 基于thread封装带返回的
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="funct"></param>
/// <returns></returns>
private func<t> threadwithreturn<t>(func<t> funct)
{
           t t = default(t);

            threadstart startnew = new threadstart(()=> {
            t = funct.invoke();
            });
            thread thread = new thread(startnew);
            thread.start();
            return new func<t>(()=> 
            {
                thread.join();
                return t;
             });
}
 
调用这个方法
{
func<int> func = this.threadwithreturn(() => 222);

console.writeline( func.invoke());

}
 
.net framework框架2.0时期,多线程,用threadpool
 
threadpool.queueuserworkitem(o=>
{
          thread.sleep(2000);
           this.dosomething("threadpool");
} //这个就是开启一个子线程。
 
如果要控制等待,就用
 manualresetevent mre = new manualresetevent(false);//默认填false
threadpool.queueuserworkitem(o => {
            thread.sleep(2000);
            this.dosomething("threadpool");
            mre.set();//这个设置之后
});
            mre.waitone();//当mre.set之后,主线程就可以等待子线程执行完成之后再执行
             
            console.writeline($"this is end ");
 
.net framework框架3.0时期,多线程,用task
 
task.run(()=>this.dosomething("task")); //就开启执行子线程了
 
推荐使用task的原因:1.使用的是线程池的线程,全部都是后台线程
                                    2、api很强大
 
taskfactory taskfactory = task.factory();
taskfactory.startnew(()=>this.dosomething("task1"));//跟task.run的效果一样
taskfactory.startnew(()=>this.dosomething("task2"));
taskfactory.startnew(()=>this.dosomething("task3"));
taskfactory.startnew(()=>this.dosomething("task4"));
taskfactory.startnew(()=>this.dosomething("task5"));//执行多个子线程
 
需要多线程加快速度,同时又要求全部完成后,执行新的任务
多业务操作希望并发,但是全部完成后,执行新的任务
 
list<task> tklist = new list<task>();
 
tklist.add(taskfactory.startnew(()=>this.dosomething("task1")));
tklist.add(taskfactory.startnew(()=>this.dosomething("task2")));
tklist.add(taskfactory.startnew(()=>this.dosomething("task3")));
 
task.waitall(tklist.toarray());
console.writeline("全部完成之后,执行任务");
 
 
需要多线程加快速度,同时又要求一个任务完成后,执行新的任务
多业务操作希望并发,但是一个任务完成后,执行新的任务
task.waitany(tklist.toarray());
console.writeline("一个任务完成之后,执行任务");
 
不过两个方法同时使用的时候,waitany放在waitall前面。
 
但是上面2个方法都会卡住ui界面
 
还有2个方法也可以执行同样的任务,而且不卡界面,类似回调
 
taskfactory.continuewhenall(tasks.toarray(), tlist => { console.writeline("全部执行完之后执行,而且不卡界面"); });
 
taskfactory.continuewhenany(tasks.toarray(), t => { console.writeline("执行一个任务后,执行,不卡界面"); });
 
4种方法可以一起使用,如果想先执行不卡界面的方法,后执行task.waitall的方法,就可以先把这2个方法也添加进集合里面
tasks.add(taskfactory.continuewhenall(tasks.toarray(), tlist => { console.writeline("全部执行完之后执行,而且不卡界面"); }));

tasks.add(taskfactory.continuewhenany(tasks.toarray(), t => { console.writeline("执行一个任务后,执行,不卡界面"); }));
 
task.waitany(tklist.toarray());
console.writeline("一个任务完成之后,执行任务");
task.waitall(tklist.toarray());
console.writeline("全部完成之后,执行任务");
 
 
可以给每个子线程,取一个标识

task tack= taskfactory.startnew(t => console.writeline("新的一个任务"),"标识token"); //设置标识
console.writeline(tack.asyncstate.tostring());//获取标识并且打印 tack.asyncstate
 
获取返回值
//task<int> task = taskfactory.startnew(()=>123456);
//int result = task.result;
//console.writeline(result);
 
 
一个线程执行后马上执行另一个
taskfactory.startnew(t=>this.dosomething("第一个方法")).continuwith(t=>console.writeline("第二个"))