Task多线程并行开发
Net 4.0之后出现的多线程对象。
Task 其实时Thread 和ThreadPool的结合和优化
Thread 通过windbg观察执行完后GC下次回收,时间空间开销不小,调用过多时间片切换频繁影响效率
ThreadPool 受限CPU核心线程数,CLR控制回收.
Task使用方法
【1】new一个新的Task来启动(包含很多的重载)
Task task = new Task(() =>
{
//在这个地方写我们需要的逻辑...
Console.WriteLine("子线程Id={0}", Thread.CurrentThread.ManagedThreadId);
});
task.Start();
我们看到还是转换成了线程池的.
【2】使用Task的Run()方法
Task task = Task.Run(() =>
{
//在这个地方写我们需要的逻辑...
Console.WriteLine("子线程Id={0}", Thread.CurrentThread.ManagedThreadId);
});
这个通过windbg查看也一样的
【3】使用TaskFactory启动(类似于ThreadPool)
Task task = Task.Factory.StartNew(() =>
{
//在这个地方写我们需要的逻辑...
Console.WriteLine("子线程Id={0}", Thread.CurrentThread.ManagedThreadId);
});
这个通过windbg查看也一样的
【4】以上是三种异步方式。对于第一种情况,我们也可以使用同步执行(阻塞)
Task task = new Task(() =>
{
Console.WriteLine("子线程开始执行......");
Thread.Sleep(1000);
Console.WriteLine("子线程Id={0}", Thread.CurrentThread.ManagedThreadId);
});
task.RunSynchronously();//这个是同步方法
现在这个我们在windbg看到时和同步方法一模一样的,用完就没了.
【5】Task还可以有返回值Task<TResult> 它的父类也是Task
var task = new Task<string>(() =>
{
//在这个地方可以编写自己的业务逻辑...
return "We are Studying Task!";
});
task.Start();
var result = task.Result;//获取结果数据
Console.WriteLine(result);
Task阻塞方法
Task task1 = new Task(()=>
{
Thread.Sleep(1000);
Console.WriteLine("This is subThread1...");
});
task1.Start();
Task task2 = new Task(() =>
{
Thread.Sleep(3000);
Console.WriteLine("This is subThread2...");
});
task2.Start();
//等待所有任务线程执行完毕再执行
var taskArray = new Task[2] { task1, task2 };
//Task.WaitAll(taskArray);
//只要有一个任务完成就可以执行后面的任务
Task.WaitAny(taskArray);
//还有task.wait()类似与join();了解一下即可不常用.
Console.WriteLine("This is Main Thread...");
【2】同学们注意了,上面的这些操作都没有返回值。
那么我们就考虑到一个延续的问题
【1】//WhenAll
Task task1 = new Task(() =>
{
Thread.Sleep(3000);
Console.WriteLine("This is subThread1...");
});
task1.Start();
Task task2 = new Task(() =>
{
Thread.Sleep(1000);
Console.WriteLine("This is subThread2...");
});
task2.Start();
Task.WhenAll(task1,task2).ContinueWith(
(task3)=>
{
Console.WriteLine("This is subThread3..."
+Thread.CurrentThread.ManagedThreadId);
});//线程的延续...(主线下不等待,子线程依次执行)
Console.WriteLine("This is Main Thread...");
//【2】线程的延续...(任何一个线程执行完,就执行后面的信任,主线程依然不等待)
// Task.WhenAny(task1, task2).ContinueWith(task3 =>
// {
// Console.WriteLine("Child(3)Time={0}", DateTime.Now.ToLongTimeString());
// });
//【3】使用工厂完成:ContinueWhenAll
以上几个都是根据自己需求来吧.都可以实现依次执行的效果,在有些需求中我们必须这样依次执行才能保证系统的正确性稳定性.
子线程的附加 TaskCreationOptions creationOptions
Task parentTask = new Task(()=>
{
Task task1 = new Task(()=>
{
Console.WriteLine("This is attact Thread1....");
},TaskCreationOptions.AttachedToParent);
task1.Start();
Task task2 = new Task(() =>
{
Console.WriteLine("This is attact Thread2....");
}, TaskCreationOptions.AttachedToParent);
task2.Start();
});
parentTask.Start();
parentTask.Wait();//等待任务完成 相当于waitall(task1,task2);
#endregion
Console.WriteLine("This is Main Thread...");
子线程附加可以用在一个大模块中,这些子线程可以附加到一个父任务中.
TaskCreationOptions枚举中还有其他枚举大家可以仔细看看
Task常见枚举 (延续、完成、取消)
Task task1 = new Task(() =>
{
Console.WriteLine("Child(1)Time={0} Id={1}", DateTime.Now.ToLongTimeString(), Thread.CurrentThread.ManagedThreadId);
});
//任务2
Task task2 = task1.ContinueWith((task) =>
{
Console.WriteLine("Child(2)Time={0} Id={1}", DateTime.Now.ToLongTimeString(), Thread.CurrentThread.ManagedThreadId);
});
//任务3
Task task3 = task2.ContinueWith((task) =>
{
Console.WriteLine("Child(3)Time={0} Id={1}", DateTime.Now.ToLongTimeString(), Thread.CurrentThread.ManagedThreadId);
});
task1.Start();//嵌套执行,只需要Start Task1 等待Task1完成 然后执行了Task1的延续,由于Task的延续又在Task2里面,Task2又可以延续。
//这里的好处就是我们需要队列执行的的时候如何保证它不冲突,这个用处就大了.