使用线程池使得创建线程已经很简单了,但是使用线程池不支持线程的取消,完成和失败通知等交互操作,为了解决这些问题,.net 4.0带来了TPL(Task Parallel Library)任务并行库,下面就来总结下Task的使用。

创建和运行任务

在.net 4.0下使用task创建一个线程非常简单,有两种方式,如下代码:

 namespace ConsoleApplication19
{
class Program
{
static void Main(string[] args)
{
//方法1
var task1 = new Task(() =>
{
Console.WriteLine("Create and start task!");
});
task1.Start(); //方法2
Task.Factory.StartNew(() =>
{
Console.WriteLine("Task factory start new task!");
}); Console.ReadKey();
}
}
}

输出结果:

需要注意的是:task也是基于线程池的,所以这两个任务的执行顺序是不固定的。

取消任务

创建一个新的任务之后,我们随时都可以取消它,取消方法如下代码:

 namespace ConsoleApplication20
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main thread starting..."); var cts = new CancellationTokenSource();
var task1 = Task.Factory.StartNew(() =>
{
TaskAction(cts.Token);
}); Thread.Sleep();
Console.WriteLine(string.Format("current task status::{0}", task1.Status)); //取消任务
cts.Cancel();
Console.WriteLine("start cancel task!");
for (int i = ; i < ; i++)
{
Thread.Sleep();
Console.WriteLine(string.Format("current task status::{0}", task1.Status));
} Console.WriteLine("Main thread completed!");
Console.ReadKey();
} public static void TaskAction(CancellationToken token)
{
Console.WriteLine("Sub thread starting..."); while (true)
{
Thread.Sleep();
if (token.IsCancellationRequested)
{
Console.WriteLine("Sub thread be cancelled!");
return;
}
Console.WriteLine("Sub thread is running!");
}
} }
}

输出结果:

创建任务集合并输出结果

如下代码:

 namespace ConsoleApplication21
{
class Program
{
static void Main(string[] args)
{
//创建任务集合并输出结果
var tasks = new List<Task<string>>(); var task1 = Task.Factory.StartNew<string>(() =>
{
Console.WriteLine("task1 running on thread id:"+ Thread.CurrentThread.ManagedThreadId);
return "task1";
});
tasks.Add(task1); var task2 = Task.Factory.StartNew<string>(() =>
{
Console.WriteLine("task2 running on thread id:" + Thread.CurrentThread.ManagedThreadId);
return "task2";
});
tasks.Add(task2); var task3 = Task.Factory.StartNew<string>(() =>
{
Console.WriteLine("task3 running on thread id:" + Thread.CurrentThread.ManagedThreadId);
return "task3";
});
tasks.Add(task3); //输出结果
foreach (var item in tasks)
{
Console.WriteLine(item.Result);//调用Task的Result方法相当于调用了Task.WaitAll(tasks.ToArray());
} Console.ReadKey();
}
}
}

输出结果:

这里要注意2点:

1,每个任务会开启一个新的线程,并且运行顺序不固定。

2,Task.Result相当于调用了Wait方法,等待异步任务完成。

多任务的串行化

如下代码:

 namespace ConsoleApplication22
{
class Program
{
static void Main(string[] args)
{
//多任务的串行化
var task1 = Task.Factory.StartNew(() =>
{
Console.WriteLine("start task1...");
Console.WriteLine("current thread id:"+ Thread.CurrentThread.ManagedThreadId);
}); var task2 = task1.ContinueWith((item) =>
{
Console.WriteLine("start task2...");
Console.WriteLine("current thread id:" + Thread.CurrentThread.ManagedThreadId);
}); var task3 = task2.ContinueWith((item)=>
{
Console.WriteLine("start task3...");
Console.WriteLine("current thread id:" + Thread.CurrentThread.ManagedThreadId);
}); Console.ReadKey();
}
}
}

输出结果:

注意,多任务串行化后,就相当于顺序执行了,而且有可能使用的是同一个线程,从上图的thread id就可以看出来。

多任务等待执行完成

如下代码:

 namespace ConsoleApplication23
{
class Program
{
static void Main(string[] args)
{
//多任务等待执行完成
var tasks = new List<Task<string>>(); var task1 = Task.Factory.StartNew<string>(() =>
{
Console.WriteLine("task1");
return "task1";
});
tasks.Add(task1); var task2 = Task.Factory.StartNew<string>(() =>
{
Console.WriteLine("task2");
return "task2";
});
tasks.Add(task2); var task3 = Task.Factory.StartNew<string>(() =>
{
Console.WriteLine("task3");
return "task3";
});
tasks.Add(task3); //等待所有任务完成
Task.WaitAll(tasks.ToArray()); //等价于下面的调用
//foreach (var item in tasks)
//{
// item.Result
//} Console.ReadKey();
}
}
}

输出结果:

需要注意的是,如果是有返回值的task,可以使用Task.Result获取返回值的同时,也在等待Task执行完成,相当于调用了Task.Wait方法。

创建子任务

如下代码:

 namespace ConsoleApplication24
{
class Program
{
static void Main(string[] args)
{
//创建子任务
var parentTask = Task.Factory.StartNew(() =>
{
Console.WriteLine("parent task!");
var childTask = Task.Factory.StartNew(() =>
{
Console.WriteLine("child task!");
}, TaskCreationOptions.AttachedToParent);
}); Console.ReadKey();
}
}
}

输出结果:

多线程(4)Task的更多相关文章

  1. 【多线程】 Task ,async ,await

    [多线程]Task ,async ,await 一. WinForm 里经常会用到多线程, 多线程的好出就不多说了,来说说多线程比较麻烦的地方 1. UI 线程与其他线程的同步,主要是 Form 和 ...

  2. 【多线程】 Task

    [多线程] Task 一. 常用方法: 1. ContinueWith : 当前 Task 完成后, 执行传入的 Task 2. Delay : 创建一个等待的 Task,只有在调用 Wait 方法时 ...

  3. .Net 多线程 (1) Task

    多线程是一种有效提高程序工作效率的方法.当然为了效率需要使用更多的cpu,内存等资源. 并发是两个队列交替使用一台咖啡机,并行是两个队列同时使用两台咖啡机,如果串行,一个队列使用一台咖啡机,那么哪怕前 ...

  4. 【多线程】Task

    介绍 Task是.NET推出数据任务处理的工作类.位于System.Threading.Tasks命名空间下,通过命名空间也可以看出是个多线程类. 创建Task: Task有很多构造函数,无参有参都有 ...

  5. C#多线程编程のTask(任务全面解析)

    Task是.NET4.0加入的,跟线程池ThreadPool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化都会创建一个新的线程. 我们可以说Task是一种基于任务的 ...

  6. C# 应用 - 多线程 3) Task.Factory

    1. 与 Task.Run() 的区别: 先看一下源码: public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable { pu ...

  7. C# 应用 - 多线程 4) Task cancel

    1. 操作取消 1.1 步骤 实例化 CancellationTokenSource 对象,该对象管理取消通知并将其发送给单个取消标记 将 CancellationTokenSource.Token ...

  8. Task/Parallel实现异步多线程

    代码: #region Task 异步多线程,Task是基于ThreadPool实现的 { //TestClass testClass = new TestClass(); //Action<o ...

  9. .NET多线程(Thread,ThreadPool,Task,Async与Await)

    .NET多线程是什么? 进程与线程 进程是一种正在执行的程序. 线程是程序中的一个执行流. 多线程是指一个程序中可以同时运行多个不同的线程来执行不同的任务. .NET中的线程 Thread是创建和控制 ...

随机推荐

  1. 已知一个字符串S 以及长度为n的字符数组a,编写一个函数,统计a中每个字符在字符串中的出现次数

    import java.util.Scanner; /** * @author:(LiberHome) * @date:Created in 2019/3/6 21:04 * @description ...

  2. es5中的for in 与es6中的for of的用法与区别

    for in 用与循环遍历对象中的属性键值 for of用于循环遍历出数组中的属性值 for in 也可以遍历数组,但是局限是他会把数组的其他属性键值也会遍历出,例如给数组添加一个属性arr.name ...

  3. ABP入门系列(2)——领域层创建实体

    ABP入门系列目录--学习Abp框架之实操演练 这一节我们主要和领域层打交道.首先我们要对ABP的体系结构以及从模板创建的解决方案进行一一对应.网上有代码生成器去简化我们这一步的任务,但是不建议初学者 ...

  4. 最新手机号正则表达式 java 、javascript版正则表达式验证是否为11位有效手机号码

    最近在做注册登陆页面,都要涉及到验证11位有效手机号码,这里贴出代码,希望能帮到有这个开发需求的朋友. function isPoneAvailable($poneInput) { var myreg ...

  5. 数组Array和列表集合ArrayList、LinkedList和Vector的区别

    一.ArrayList和Vector的区别 ArrayList与Vector主要从以下方面来说. 1.同步性: Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同 ...

  6. [Swift]LeetCode223. 矩形面积 | Rectangle Area

    Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle is defined b ...

  7. [Swift]LeetCode384. 打乱数组 | Shuffle an Array

    Shuffle a set of numbers without duplicates. Example: // Init an array with set 1, 2, and 3. int[] n ...

  8. [Swift]LeetCode629. K个逆序对数组 | K Inverse Pairs Array

    Given two integers n and k, find how many different arrays consist of numbers from 1 to n such that ...

  9. [Swift]LeetCode753. 破解保险箱 | Cracking the Safe

    There is a box protected by a password. The password is n digits, where each letter can be one of th ...

  10. 深入理解OkHttp源码(三)——网络操作

    这篇博客侧重于了解OkHttp的网络部分,包括Socket的创建.连接,连接池等要点.OkHttp对Socket的流操作使用了Okio进行了封装,本篇博客不做介绍,想了解的朋友可以参考拆轮子系列:拆O ...