码迷,mamicode.com
首页 > 编程语言 > 详细

多线程-Task、await/async

时间:2017-09-24 23:45:29      阅读:679      评论:0      收藏:0      [点我收藏+]

标签:child   简单   定义   状态机   back   order   代码   default   each   

Task创建无返回值

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

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

Task创建主要有三种方式

1、Task参数

技术分享
Task t = new Task(() =>
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(i);
    }
});
t.Start();
View Code

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

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

CancellationToken:线程取消通知

TaskCreationOptions:控制Task的执行方式

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

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 = 10; i < 20; i++)
    {
        Console.WriteLine(i);
    }
});
View Code

3、TaskFactory

Task.Factory是TaskFactory的一个实例。

技术分享
TaskFactory tf = new TaskFactory();
tf.StartNew(() =>
{
    for (int i = 20; i < 30; i++)
    {
        Console.WriteLine(i);
    }
});
View Code

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

Task创建有返回值

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

技术分享
Task<string> t = new Task<string>(GetName);
t.Start();
Console.WriteLine(t.Result);
Console.WriteLine("结束");
View Code
技术分享
public static string GetName()
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(i);
    }
    return "臧峰";
}
View Code

注意在获取返回值的时候,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回调

还是先了解一下TaskFactory

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 = 0;
    for (int i = 0; i < 10000; i++)
    {
        Thread.Sleep(10);
        if (!clt.IsCancellationRequested)
        {
            temp += i;
        }
        else
        {
            break;
        }
    }
    Console.WriteLine(temp);
});
Thread.Sleep(200);
clt.Cancel();
View Code
Task返回值

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

技术分享
Task<int> t = new Task<int>(() => 5);
t.Start();
Console.WriteLine(t.Result);



TaskFactory<int> tf = new TaskFactory<int>();
var  tft= tf.StartNew(() => { return 6; });
Console.WriteLine(tft.Result);
View Code

最后通过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; }
View Code

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

5、总结

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

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、原理

是一个语法糖,利用一个状态机的概念,通过编译器编译把一部分代码封装为回调,状态机就是这一个执行完之后,就movenest执行下一个回调。就是await一层层的嵌套就可以了。

3、使用

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

返回值只能是void task  task<>,推荐使用task<>返回值。

 

本文代码下载

多线程-Task、await/async

标签:child   简单   定义   状态机   back   order   代码   default   each   

原文地址:http://www.cnblogs.com/wudequn/p/7571039.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!