Task创建无返回值

Task是.netframwork4.0重新分装的多线程类。原因以前的多线程(thread threadpool)不好用。(.net framwork也是的发展的,现在的EF,刚开始是一个edmx文件,现在的code first,ef轻量级。但是其他有的技术也是死掉了)

Task具有线程执行的可控性,返回值,代码书写简单,性能好等特点。

Task创建主要有三种方式

1、Task参数

Task t = new Task(() =>
{
for (int i = ; i < ; i++)
{
Console.WriteLine(i);
}
});
t.Start();

Action,Action<object>,object state,CancellationToken,TaskCreationOptions

Action<object>:task创建有参数的任务,参数只能是object

object:带有参数委托的参数。

CancellationToken:线程取消通知

TaskCreationOptions:控制Task的执行方式

//
// 摘要:
// 指定可控制任务的创建和执行的可选行为的标志。
[Flags]
public enum TaskCreationOptions
{
//
// 摘要:
// 指定应使用默认行为。
None = ,
//
// 摘要:
// 提示 System.Threading.Tasks.TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。
PreferFairness = ,
//
// 摘要:
// 指定任务将是长时间运行的、粗粒度的操作,涉及比细化的系统更少、更大的组件。它会向 System.Threading.Tasks.TaskScheduler
// 提示,过度订阅可能是合理的。您可以通过过度订阅创建比可用硬件线程数更多的线程。
LongRunning = ,
//
// 摘要:
// 指定将任务附加到任务层次结构中的某个父级。有关详细信息,请参阅 已附加和已分离的子任务。
AttachedToParent = ,
//
// 摘要:
// 如果尝试附有子任务到创建的任务,指定 System.InvalidOperationException 将被引发。
DenyChildAttach = ,
//
// 摘要:
// 防止环境计划程序被视为已创建任务的当前计划程序。这意味着像 StartNew 或 ContinueWith 创建任务的执行操作将被视为 System.Threading.Tasks.TaskScheduler.Default
// 当前计划程序。
HideScheduler =
}

2、Task.Factory.StartNew

Action,Action<object>,object state,CancellationToken,TaskCreationOptions,TaskScheduler

TaskScheduler:定义:用于计划所创建的 System.Threading.Tasks.Task 的 System.Threading.Tasks.TaskScheduler。(并看不出来是什么意思,英文意思 任务调度器)

返回值是一个Task

Task.Factory.StartNew(() =>
{
for (int i = ; i < ; i++)
{
Console.WriteLine(i);
}
});

3、TaskFactory

Task.Factory是TaskFactory的一个实例。

TaskFactory tf = new TaskFactory();
tf.StartNew(() =>
{
for (int i = ; i < ; i++)
{
Console.WriteLine(i);
}
});

上面的都是不带返回参数的任务

Task创建有返回值

一般项目中的返回类型都会特定的封装一个通用的类型。所有都会有返回值。

Task<string> t = new Task<string>(GetName);
t.Start();
Console.WriteLine(t.Result);
Console.WriteLine("结束");
public static string GetName()
{
for (int i = ; i < ; i++)
{
Console.WriteLine(i);
}
return "臧峰";
}

注意在获取返回值的时候,t.Result会卡着线程,一只等待线程返回结果。

Task等待

1、为什么要等待呢,因为线程大部分都要计算已给结果,所以我们要等待这个结果。

2、public void Wait(。。。。);

位于Task类中(实例方法。另外还有几个静态方法)。

定义:等待 System.Threading.Tasks.Task 完成执行过程(卡着其他线程)。

参数可以设置等待时间,CancellationToken(任务取消)  等待期间可以取消任务。

3、public static void WaitAll(params Task[] tasks....);

定义:等待提供的所有 System.Threading.Tasks.Task 对象完成执行过程。(就是当前线程要等这个参数列表中线程全部执行完后  才执行。注意:waitall前面其他的子线程还是在继续执行)

参数:等待任务列表,事件,CancellationToken

4、public static int WaitAny(params Task[] tasks);

定义:等待提供的任一 System.Threading.Tasks.Task 对象完成执行过程。

参数:等待任务列表,事件,CancellationToken

5、Task的属性方法

AsyncState 就是当任务核心方法带参数的时候,参数值
Status 任务执行进度的状态
CreationOptions 任务创建和执行的行为
Id 任务线程ID
IsCanceled 任务是否被取消
IsCompleted 任务是否完成
IsFaulted 任务是否失败
Result 任务返回值,该值只适用于有返回参数的任务
ContinueWith() 线程执行完之后执行另外一个任务
GetAwaiter() 获取等待这个线程的等待着
Start() 发起一个任务
Wait() 当前调用wait的任务线程等待

这些是常用的

Task回调
//------------------------Task回调-------------------------
Task<int> t = new Task<int>(() =>
{
var temp = ;
for (int i = ; i < ; i++)
{
temp += i;
}
return temp;
}); t.ContinueWith<string>((f) =>
{
Console.WriteLine(f.Result.ToString());
return f.Result.ToString();
});
t.Start(); //------------------TaskFactory回调----------------------------
TaskFactory<int> tf = new TaskFactory<int>();
var tft = tf.StartNew(() =>
{
var temp = ;
for (int i = ; i < ; i++)
{
temp += i;
}
return temp;
});
tft.ContinueWith<string>((f) =>
{
Console.WriteLine(f.Result.ToString());
return f.Result.ToString();
}); //-----------------------ContinueWhenAll--------------------------
var cts = new CancellationTokenSource();
TaskFactory<int> tf1 = new TaskFactory<int>(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); Task<int> t1 = tf1.StartNew(() => { Console.WriteLine(); return ; });
Task<int> t2 = tf1.StartNew(() => { Console.WriteLine(); return ; });
Task<int> t3 = tf1.StartNew(() => { Console.WriteLine(); return ; });
Task<int> t4 = tf1.StartNew(() => { Console.WriteLine(); return ; });
Task<int> t5 = tf1.StartNew(() => { Console.WriteLine(); return ; }); //意思就是说当这些所有的线程都执行完了,在执行后面的线程
//第一个参数就是要执行的线程数组
//第二个参数就是 继续执行的线程
var tcwa = tf1.ContinueWhenAll(new[] { t1, t2, t3, t4, t5 }, tlReturn =>
{
int temp = ;
for (int i = ; i < tlReturn.Length; i++)
{
temp += tlReturn[i].Result;
}
Console.WriteLine(temp);
return temp;
}); var tft1 = tf1.StartNew(() =>
{
var temp = ;
for (int i = ; i < ; i++)
{
temp += i;
}
Console.WriteLine(temp);
return temp;
}); //-------------------------FromAsync-----------------------------------
TaskFactory<long> tfFA = new TaskFactory<long>();
Func<long> faDel = (() =>
{
Console.WriteLine("臧锋");
return ;
});
tfFA.FromAsync(faDel.BeginInvoke(null, null), (tr) =>
{
Console.WriteLine(tr.IsCompleted);
return ;
});

还是先了解一下TaskFactory

ContinueWhen不会卡当前线程。wait会卡当前线程。

CancellationToken 任务取消标记
ContinuationOptions 字面意思 任务延续选择。官方注释不敢恭维。和ContinueWhenAll、ContinueWhenAny有关
CreationOptions 指定此任务工厂的默认创建选项。(任务执行顺序,是否长时间执行...)
Scheduler 任务工厂的任务计划程序。表示一个处理将任务排队到线程中的低级工作的对象。
ContinueWhenAll

创建一个延续任务,它将在提供的组中的所有任务完成后马上开始。第一个参数P1:线程列表,就是要执行的线程

(必须有调用ContinueWhenAll的TaskFactory创建)    第二个参数P2:回调函数

(回调函数的第一个参数为第一个参数P1,回调函数第二个参数为返回值,由TaskFactory<>定义的)。

执行顺序  P1先执行,然后P2执行。   TaskFactory的任务为随机执行

ContinueWhenAny 创建一个延续任务,它将在提供的组中的任何任务完成后马上开始。
FromAsync

创建一个任务,它在指定的 System.IAsyncResult 完成时执行一个结束方法函数。(官方解释有点绕  其实就是

通过它可以把一个异步的任务转换为一个Task,返回值是一个Task,最后在执行一个回调函数)

吐槽一下,官方的翻译是不是都是电脑翻译的。

StartNew 创建开启任务
Task取消

主要是类CancellationTokenSource

定义:通知 System.Threading.CancellationToken,告知其应被取消。

可以马上取消,还可以设置时间取消。

CancellationTokenSource clt = new CancellationTokenSource();
TaskFactory tf = new TaskFactory(clt.Token);
tf.StartNew(() =>
{
int temp = ;
for (int i = ; i < ; i++)
{
Thread.Sleep();
if (!clt.IsCancellationRequested)
{
temp += i;
}
else
{
break;
}
}
Console.WriteLine(temp);
});
Thread.Sleep();
clt.Cancel();
Task返回值

具有返回值的是要用泛型  指定返回值类型。

Task<int> t = new Task<int>(() => );
t.Start();
Console.WriteLine(t.Result); TaskFactory<int> tf = new TaskFactory<int>();
var tft= tf.StartNew(() => { return ; });
Console.WriteLine(tft.Result);

最后通过Task.Result得到结果。这个操作会卡着线程,一直等待回去结果。

 Parallel并行任务

1、Parallel  定义:提供对并行循环和区域的支持。静态类,静态方法。他是基于Task,线程池。

其实是操作循环任务,但是循环的任务都是在平行执行的,没人先后顺序,但是,循环结会等待他们都结束的。

Parallel.For

Parallel.ForEach

Parallel.Invok

优点:主线程也会参与计算,缺点:就是会waitall   会卡住当前线程。

2、ParallelLoopResult 定义:提供执行 System.Threading.Tasks.Parallel 循环的完成状态。其实就是For和ForEach的返回值

3、ParallelLoopState 定义:可用来使 System.Threading.Tasks.Parallel 循环的迭代与其他迭代交互。此类的实例由 Parallel 类提供给每个循环;不能在您的用户代码中创建实例。

他可以让循环退出 ,通知。  (就像for循环中的bread)

4、ParallelOptions 定义:存储用于配置 System.Threading.Tasks.Parallel 类的方法的操作的选项。

//
// 摘要:
// 获取或设置与此 System.Threading.Tasks.ParallelOptions 实例关联的 System.Threading.CancellationToken。
//
// 返回结果:
// 与此实例关联的标记。
public CancellationToken CancellationToken { get; set; }
//
// 摘要:
// 获取或设置此 System.Threading.Tasks.ParallelOptions 实例所允许的最大并行度。
//
// 返回结果:
// 一个表示最大并行度的整数。
//
// 异常:
// T:System.ArgumentOutOfRangeException:
// 该属性被设置为 0 或小于 -1 的值。
public int MaxDegreeOfParallelism { get; set; }
//
// 摘要:
// 获取或设置与此 System.Threading.Tasks.ParallelOptions 实例关联的 System.Threading.Tasks.TaskScheduler。将此属性设置为
// null,以指示应使用当前计划程序。
//
// 返回结果:
// 与此实例关联的任务计划程序。
public TaskScheduler TaskScheduler { get; set; }

可以取消任务,并行的数量(循环中一次并行执行任务的个数,当任务量比较大的时候,一定要指定这个值,不然电脑可能撑不住。但是他是基于线程池的,线程池会帮我们控制一下,但是还是会卡电脑。并行数量控制,导致起的线程是一轮一轮的,每一轮第一个线程ID都一样,用的主线程ID)

5、总结

Parallel.For()和Paraller.ForEach()方法在每次迭代中调用相同的代码,而Parallel.Invoke()方法允许同时调用不同的方法。Parallel.ForEach()用于数据并行性,Parallel.Invoke()用于任务并行性;

主线程可以参与计算,但是要waitall。等待。

Await Async

1、出现介绍

C#5.0                  C#语言版本

.net fromwork 4.5                框架类库版本FCL

clr4.0                  CLR版本

await async他是一个语法糖。什么是语法糖呢,就是c#或者.net fromwork改变但是clr没有改变。

泛型就不是语法糖,他出现的时候clr重写了,就是使用泛型的地方,  对应的生成相应的类型方法。

没有task就没有await async

2、原理

是一个语法糖,利用一个状态机的概念,通过编译器编译把await后面的代码封装为一个委托进行回调执行,并且await会等待执行完成,状态机就是这一个执行完之后,就movenest执行下一个回调。就是await一层层的嵌套就可以了。

3、使用

await只能出现在task前面,await后面的代码变成task的回调。快速的写出了异步回调

返回值只能是void task  task<>,推荐使用task<>返回值,并封装通用T类型。

本文代码下载

补充例子

多线程-Task、await/async的更多相关文章

  1. C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较

    使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新 使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和 ...

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

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

  3. C#多线程和异步(二)——Task和async/await详解

    一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...

  4. C#多线程和异步(二)——Task和async/await详解(转载)

    一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...

  5. C#多线程和异步——Task和async/await详解

    阅读目录 一.什么是异步 二.Task介绍 1 Task创建和运行 2 Task的阻塞方法(Wait/WaitAll/WaitAny) 3 Task的延续操作(WhenAny/WhenAll/Cont ...

  6. .NET(C#):await返回Task的async方法

    众所周知,async方法只可以返回void,Task和Task<T>. 对于返回void的async方法,它并不是awaitable,所以其他方法不能用await方法来调用它,而返回Tas ...

  7. C#中 Thread,Task,Async/Await,IAsyncResult 的那些事儿!

    说起异步,Thread,Task,async/await,IAsyncResult 这些东西肯定是绕不开的,今天就来依次聊聊他们 1.线程(Thread) 多线程的意义在于一个应用程序中,有多个执行部 ...

  8. 从Thread,ThreadPool,Task, 到async await 的基本使用方法解读

    记得很久以前的一个面试场景: 面试官:说说你对JavaScript闭包的理解吧? 我:嗯,平时都是前端工程师在写JS,我们一般只管写后端代码. 面试官:你是后端程序员啊,好吧,那问问你多线程编程的问题 ...

  9. Thread,ThreadPool,Task, 到async await 的基本使用方法和理解

    很久以前的一个面试场景: 面试官:说说你对JavaScript闭包的理解吧? 我:嗯,平时都是前端工程师在写JS,我们一般只管写后端代码. 面试官:你是后端程序员啊,好吧,那问问你多线程编程的问题吧. ...

随机推荐

  1. syniverse是一家怎样的公司

    syniverse是一家怎样的公司?(详见问题描述)? 李超   核心业务当然是国际漫游了.简单来说就是做全球各个运营商之间的hub. 打个比方说,一家运营商A做通信,它的覆盖范围肯定是有限的(比如中 ...

  2. Redis使用总结(二、缓存和数据库双写一致性问题)

    首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用.在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作. 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存.又或者 ...

  3. Storage Port Drivers

    为了学习存储知识,我也是拼了,来,翻译一下下面这篇微软的文章(如果有谁翻译过了,或者微软有中文翻译,请绕路): Storage Port Drivers Last Updated: 4/20/2017 ...

  4. IDEA正确设置编码统一为UTF-8

    之前代码在myeclispe10跑得好好的来这个intellij idea 就一直出错 改了好久的编码都没卵用,如下设置才正确.还有idea的web工程目录和myeclispe的目录是不一样的,神坑. ...

  5. [vsftpd] ubuntu14.04 ansible剧本安装vsftpd流程及报错排查

    需求: 在ubuntu14.04机器上搭建ftp服务,ftp账号通过winscp软件登录后,仅可增删改/data/wwwroot目录. 一.安装步骤 1.apt 安装vsftpd apt-get in ...

  6. luogu_P4767 [IOI2000]邮局

    传送门 Description 高速公路旁边有一些村庄.高速公路表示为整数轴,每个村庄的位置用单个整数坐标标识.没有两个在同样地方的村庄.两个位置之间的距离是其整数坐标差的绝对值. 邮局将建在一些,但 ...

  7. Linux用户组

    1.介绍 类似于角色,系统可以对有共性的多个用户进行统一的管理 2.增加组 groupadd  组名 3.删除组 groupdel  组名 4.增加用户时直接为用户指定组 useradd  -g  用 ...

  8. C++的面向对象的Dijkstra写法

    C++的面向对象的Dijkstra写法 面向对象特点的充分使用 清晰的逻辑 简洁的图输入 程序 面向对象特点的充分使用 清晰明确的类实现 class Edge(边的实现) class Req (路由请 ...

  9. 5.linux 软件安装的三种方法

      一.linux 操作系统中 软件的分类 以及软件的安装     vmtools  调用了perl语言写的安装脚本去进行内核的升级安装  ./ xxxxx        源码包安装软件:GNU  使 ...

  10. sqlserver 触发器语法

    语法:Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger)CREATE TRIGGER ...