捌函数编制程序轻松入门,NET中的八线程

前言

在.net4.0之后异步操作,并行总结变得非凡不难,不过由于公司项目开发基于.net三.5为此不可能用到四.0的并行计算以及Task等异步编制程序。因此,为了现在更方便的实行异步方式的支出,小编封装达成了异步编制程序框架,通过BeginInvoke、EndInvoke的艺术完结异步编制程序。

 

在C#中,微软基于IEnumerable接口,提供许多便当的壮大方法,便于实际的开发。在Java
壹.第88中学,Collection接口新增了default
stream方法。我们得以本着java集合,在stearm()上,能够使用链式函数式编程。

架构

整个框架包含八个部分

  1. 基类抽象Opeartor
    异步操作的基类,达成了异步操作接口
  2. FuncAsync
    异步的Func
  3. ActionAsync
    异步的Action
  4. Asynchorus
    对ActionAsync和FuncAsync的封装

    ### Operator

    Operator是一个抽象类,实现了IOperationAsyncIContinueWithAsync多个接口。
    IOperationAsync福衢寿车了异步操作,IContinueWithAsync贯彻了类似于Task的ContinueWith方法,在近日异步操作完毕后持续开始展览的操作

    #### IOperationAsync接口详解

    public interface IOperationAsync
    {
        IAsyncResult Invoke();
        void Wait();
        void CompletedCallBack(IAsyncResult ar);
        void CatchException(Exception exception);
    }
    
  • Invoke():异步方法的调用
  • Wait():等待异步操作实践
  • CompletedCallBack():操作实现回调
  • CatchException():抓取很是

上一节大家介绍了线程池相关的定义以及用法。大家能够发现ThreadPool.
QueueUserWorkItem是一种起了线程之后就随便了的做法。但是实际上运用进程,大家反复会有越来越多的急需,比如假如更简便易行的知道线程池里面的少数线程几时结束,线程甘休后怎么履行其他任务。Task能够说是ThreadPool的升迁版,在线程职务调度,并行编制程序中都有极大的功力。

  • ### 壹、外部迭代

  • 率先调用iterator方法,发生一个新的Iterator对象,进而决定总体迭代进程。(迭代历程通过体现调用Iterator对象的hasNext和next方法成功迭代)

IContinueWithAsync接口详情

public interface IContinueWithAsync
{
    Operator Previous { get; set; }
    Operator Next { get; set; }
    Operator ContinueWithAsync(Action action);
    Operator ContinueWithAsync<TParameter>(Action<TParameter> action, TParameter parameter);
}
  • Previous:前3个操作
  • Next:下多少个操作
  • ContinueWithAsync():异步继续操作

public abstract class Operator : IOperationAsync, IContinueWithAsync
{
    public IAsyncResult Middle;
    public readonly string Id;
    public Exception Exception { get; private set; }
    public Operator Previous { get; set; }
    public Operator Next { get; set; }
    protected Operator()
    {
        Id = Guid.NewGuid().ToString();
    }
    public abstract IAsyncResult Invoke();
    protected void SetAsyncResult(IAsyncResult result)
    {
        this.Middle = result;
    }
    public virtual void Wait()
    {
        if (!Middle.IsCompleted) Middle.AsyncWaitHandle.WaitOne();
    }
    public virtual void CompletedCallBack(IAsyncResult ar)
    {
    }
    public void CatchException(Exception exception)
    {
        this.Exception = exception;
    }
    protected Operator ContinueAsync()
    {
        if (Next != null) Next.Invoke();
        return Next;
    }
    public virtual Operator ContinueWithAsync(Action action)
    {
        Next = new ActionAsync(action);
        Next.Previous = this;
        return Next;
    }
    public virtual Operator ContinueWithAsync<TParameter>(Action<TParameter> action, TParameter parameter)
    {
        Next = new ActionAsync<TParameter>(action, parameter);
        Next.Previous = this;
        return Next;
    }
    public virtual Operator ContinueWithAsync<TResult>(Func<TResult> func)
    {
        Next = new FuncAsync<TResult>();
        Next.Previous = this;
        return Next;
    }
    public virtual Operator ContinueWithAsync<TParameter, TResult>(Func<TParameter, TResult> func,
        TParameter parameter)
    {
        Next = new FuncAsync<TParameter, TResult>(func, parameter);
        Next.Previous = this;
        return Next;
    }
}

创造并且早先化Task

无重回异步操作

选用lambda表明式成立Task

            Task.Factory.StartNew(() => Console.WriteLine("Hello from a task!"));

            var task = new Task(() => Console.Write("Hello"));
            task.Start();

  

  public static void main(String[] args) {
        Collection<String> list = new ArrayList<>();
        list.add("Android");
        list.add("iPhone");
        list.add("Windows Mobile");

        Iterator<String> itr = list.iterator();
        while (itr.hasNext()) {
            String lang = itr.next();
            System.out.println(lang);
        }
    }

ActionAsync

public class ActionAsync : Operator
{
    private readonly Action _action;
    protected ActionAsync()
    {
    }
    public ActionAsync(Action action)
        : this()
    {
        this._action = action;
    }
    public override IAsyncResult Invoke()
    {
        var middle = _action.BeginInvoke(CompletedCallBack, null);
        SetAsyncResult(middle);
        return middle;
    }
    public override void CompletedCallBack(IAsyncResult ar)
    {
        try
        {
            _action.EndInvoke(ar);
        }
        catch (Exception exception)
        {
            this.CatchException(exception);
        }
        ContinueAsync();
    }
}
public class ActionAsync<T> : ActionAsync
{
    public T Result;
    private readonly Action<T> _action1;
    protected readonly T Parameter1;
    public ActionAsync()
    {
    }
    public ActionAsync(T parameter)
    {
        this.Parameter1 = parameter;
    }
    public ActionAsync(Action<T> action, T parameter)
    {
        this._action1 = action;
        this.Parameter1 = parameter;
    }
    public override IAsyncResult Invoke()
    {
        var result = _action1.BeginInvoke(Parameter1, CompletedCallBack, null);
        SetAsyncResult(result);
        return result;
    }
    public override void CompletedCallBack(IAsyncResult ar)
    {
        try
        {
            _action1.EndInvoke(ar);
        }
        catch (Exception exception)
        {
            this.CatchException(exception);
        }
        ContinueAsync();
    }
}

用暗许参数的信托创建Task

using System;
using System.Threading.Tasks;

namespace MultiThread
{
    class ThreadTest
    {
        static void Main()
        {
            var task = Task.Factory.StartNew(state => Greet("Hello"), "Greeting");
            Console.WriteLine(task.AsyncState);   // Greeting
            task.Wait();
        }

        static void Greet(string message) { Console.Write(message); }

    }
}

  

那种方法的3个亮点是,task.AsyncState作为三个停放的习性,能够在区别线程中取得参数的意况。

  • ### 二、内部迭代

  • 是基于stream使用函数式编制程序的法子在联谊上海展览中心开复杂的操作。(类似于C#基于IEnumerable的扩大方法,eg:Where()方法)

  • 在函数式编制程序中,将函数作为参数来传递,传递进程中不会举行函数内部耗费时间的盘算,直到须求以此结果的时候才调用,那样就能够幸免某些不要求的计量而更上①层楼质量。
  • 在Java的stream()方法中,有惰性求值方法及早求值方法
  • 重返值为Stream为惰性求职方法。
  • 重临值为空恐怕别的值为及早求职方法

  • ### 三、常用的Stream API(也正是IEnumerable的扩张方法表)

    示范代码的功底代码

有再次来到异步

FuncAsync实现了IFuncOperationAsync接口

System.Threading.Tasks.TaskCreateOptions

始建Task的时候,大家得以钦定成立Task的1部分连锁选项。在.Net
四.0中,有如下选项:

IFuncOperationAsync

public interface IFuncOperationAsync<T>
{
    void SetResult(T result);
    T GetResult();
}
  • SetResult(T result):异步操作实现安装再次来到值
  • GetResult():获取再次来到值

    #### FuncAsync

    public class FuncAsync<TResult> : Operator, IFuncOperationAsync<TResult>
    {
    private TResult _result;
    
    public TResult Result
    {
        get
        {
            if (!Middle.IsCompleted || _result == null)
            {
                _result = GetResult();
            }
            return _result;
        }
    }
    private readonly Func<TResult> _func1;
    public FuncAsync()
    {
    }
    public FuncAsync(Func<TResult> func)
    {
        this._func1 = func;
    }
    public override IAsyncResult Invoke()
    {
        var result = _func1.BeginInvoke(CompletedCallBack, null);
        SetAsyncResult(result);
        return result;
    }
    public override void CompletedCallBack(IAsyncResult ar)
    {
        try
        {
            var result = _func1.EndInvoke(ar);
            SetResult(result);
        }
        catch (Exception exception)
        {
            this.CatchException(exception);
            SetResult(default(TResult));
        }
        ContinueAsync();
    }
    public virtual TResult GetResult()
    {
        Wait();
        return this._result;
    }
    public void SetResult(TResult result)
    {
        _result = result;
    }
    }
    public class FuncAsync<T1, TResult> : FuncAsync<TResult>
    {
    protected readonly T1 Parameter1;
    private readonly Func<T1, TResult> _func2;
    public FuncAsync(Func<T1, TResult> action, T1 parameter1)
        : this(parameter1)
    {
        this._func2 = action;
    }
    protected FuncAsync(T1 parameter1)
        : base()
    {
        this.Parameter1 = parameter1;
    }
    public override IAsyncResult Invoke()
    {
        var result = _func2.BeginInvoke(Parameter1, CompletedCallBack, null);
        SetAsyncResult(result);
        return result;
    }
    public override void CompletedCallBack(IAsyncResult ar)
    {
        try
        {
            var result = _func2.EndInvoke(ar);
            SetResult(result);
        }
        catch (Exception exception)
        {
            CatchException(exception);
            SetResult(default(TResult));
        }
        ContinueAsync();
    }
    }
    

    ### Asynchronous 异步操作封装

    ActionAsync和FuncAsync为异步操作打下了基础,接下去最主要的干活就是经过那多少个类执行大家的异步操作,为此笔者封装了2个异步操作类
    驷不及舌封装了以下多少个部分:

  1. WaitAll(IEnumerable<Operator> operations):等待全体操作实践完结
  2. WaitAny(IEnumerable<Operator> operations):等待任意操作实施达成
  3. ActionAsync
  4. FuncAsync
  5. ContinueWithAction
  6. ContinueWithFunc

    前边两个带有若干个重载,那里只是暧昧的表示2个项目标法子

    #### WaitAll

    public static void WaitAll(IEnumerable<Operator> operations)
    {
    foreach (var @operator in operations)
    {
        @operator.Wait();
    }
    }
    

    #### WaitAny

    public static void WaitAny(IEnumerable<Operator> operations)
    {
    while (operations.All(o => !o.Middle.IsCompleted))
        Thread.Sleep(100);
    }
    

    等待时间能够自定义

    #### ActionInvoke

    public static Operator Invoke(Action action)
    {
    Operator operation = new ActionAsync(action);
    operation.Invoke();
    return operation;
    }
    public static Operator Invoke<T>(Action<T> action, T parameter)
    {
    Operator operation = new ActionAsync<T>(action, parameter);
    operation.Invoke();
    return operation;
    }
    public static Operator Invoke<T1, T2>(Action<T1, T2> action, T1 parameter1, T2 parameter2)
    {
    Operator operation = new ActionAsync<T1, T2>(action, parameter1, parameter2);
    operation.Invoke();
    return operation;
    }
    

    #### FuncInvoke

    public static Operator Invoke<TResult>(Func<TResult> func)
    {
    Operator operation = new FuncAsync<TResult>(func);
    operation.Invoke();
    return operation;
    }
    public static Operator Invoke<TParameter, TResult>(Func<TParameter, TResult> func, TParameter parameter)
    {
    TParameter param = parameter;
    Operator operation = new FuncAsync<TParameter, TResult>(func, param);
    operation.Invoke();
    return operation;
    }
    public static Operator Invoke<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 parameter1, T2 parameter2)
    {
    Operator operation = new FuncAsync<T1, T2, TResult>(func, parameter1, parameter2);
    operation.Invoke();
    return operation;
    }
    

    #### ContinueWithAction

    public static Operator ContinueWithAsync(IEnumerable<Operator>operators, Action action)
    {
    return Invoke(WaitAll, operators)
        .ContinueWithAsync(action);
    }
    public static Operator ContinueWithAsync<TParameter>(IEnumerable<Operator> operators, Action<TParameter> action, TParameter parameter)
    {
    return Invoke(WaitAll, operators)
        .ContinueWithAsync(action, parameter);
    }
    

    #### ContinueWithFunc

    public static Operator ContinueWithAsync<TResult>(IEnumerable<Operator> operators,Func<TResult> func)
    {
    return Invoke(WaitAll, operators)
        .ContinueWithAsync(func);
    }
    public static Operator ContinueWithAsync<TParameter, TResult>(IEnumerable<Operator> operators, 
    Func<TParameter, TResult> func, TParameter parameter)
    {
    return Invoke(WaitAll, operators)
        .ContinueWithAsync(func, parameter);
    }
    

    那里有个bug当调用ContinueWithAsync后不可能调用Wait等待,本来Wait供给在此以前未来等待每种异步操作,不过测试了下不切合预期结果。可是理论上的话应该无需那样操作,ContinueWithAsync只是为着当上2个异步操作实施实现时继续执行的异步操作,若要等待,那不比七个操作放到1起,最后再伺机依旧得以兑现。

如今的都以单步异步操作的调用,若必要对某集合实行有个别方法的异步操作,能够foreach遍历

public void ForeachAsync(IEnumerbale<string> parameters)
{
    foreach(string p in parameters)
    {
        Asynchronous.Invoke(Tast,p);
    }
}
public void Test(string parameter)
{
    //TODO:做一些事
}

历次都供给去手写foreach,相比较费心,由此达成类似于PLinq的并行总计方法其实有必不可缺,不过有少数异样,PLinq是运用多核CPU举行并行总计,而小编封装的可是遍历集合进行异步操作而已

LongRunning

用来表示那么些Task是旷日持久运转的,那几个参数更适合block线程。LongRunning线程1般回收的周期会比较长,因而CLOdyssey恐怕不会把它内置线程池中开始展览田管。

public class Artist {
    private String name;

    private int age;

    public Artist() {
    }

    public Artist(String n, int a) {
        this.name = n;
        this.age = a;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<Artist> getArtists() {
        List<Artist> artists = new ArrayList<Artist>();
        artists.add(new Artist("lily", 20));
        artists.add(new Artist("Lucy", 21));
        artists.add(new Artist("jack", 19));
        return artists;
    }
}

ForeachAction

public static IEnumerable<Operator> Foreach<TParameter>(IEnumerable<TParameter> items, Action<TParameter> action)
{
    return items.Select(t => Invoke(action, t)).ToList();
}

PreferFairness

代表让Task尽量以公允的不2秘诀运维,防止出现有些线程运行过快依旧过慢的事态。

  • #### 1.collect(Collectors.toList())

  • 该措施正是将Stream生成三个列表,也就是C#的ToList()

ForeachFunc

public static IEnumerable<Operator> Foreach<TParameter, TResult>(IEnumerable<TParameter> items, Func<TParameter, TResult> func)
{
    return items.Select(parameter => Invoke(func, parameter)).ToList();
}

AttachedToParent

意味着创设的Task是日前线程所在Task的子任务。这个用处也很广阔。

下边包车型客车代码是创设子职务的以身作则:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace MultiThread
{
    class ThreadTest
    {
        public static void Main(string[] args)
        {
            Task parent = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("I am a parent");

                Task.Factory.StartNew(() =>        // Detached task
                {
                    Console.WriteLine("I am detached");
                });

                Task.Factory.StartNew(() =>        // Child task
                {
                    Console.WriteLine("I am a child");
                }, TaskCreationOptions.AttachedToParent);
            });

            parent.Wait();

            Console.ReadLine();
        }

    }
}

  

万1你等待你1个职务达成,你不能够不一样时等待任务之中的子任务完成。那点很关键,尤其是您在使用Continue的时候。(前面会介绍)

如何运用

  • 无再次来到值异步方法调用

    public void DoSomeThing()
    {
    //TODO:
    }
    

    通过Asynchronous.Invoke(DoSomeThing) 执行

    public void DoSomeThing(string parameter)
    {
    //TODO:
    }
    

    通过Asynchronous.Invoke(DoSomeThing,parameter) 执行

  • 有再次来到值异步方法调用

    public string DoSomeThing()
    {
    //TODO:
    }
    

    通过Asynchronous.Invoke(()=>DoSomeThing())执行

    public string DoSomeThing(string parameter)
    {
    //TODO:
    }
    

    通过Asynchronous.Invoke(()=>DoSomeThing(parameter))实践,可能也能够流传参数通过Asynchronous.Invoke(p=>DoSomeThing(p),parameter)

  • 无重临值Foreach

    public void Test
    {
    int[] parameters = {1,2,3,4,5};
    Asynchronous.Foreach(parameters,Console.WriteLine);
    }
    
  • 有再次来到值Foreach

    public void Test
    {
    int[] parameters = {1,2,3,4,5};
    var operators = Asynchronous.Foreach(parameters,p=> p*2);
    Asynchrous.WaitAll(operators);
    Asynchronous.Foreach(operators.Cast<FuncAsync<int,int>>(),
        p=> Console.WriteLine(p.Result));
    }
    

    率先将集纳每一种值扩张二倍,然后输出

  • 异步执行完再实践

    public void Test
    {
    int[] parameters = {1,2,3,4,5};
    var operators = Asynchronous.Foreach(parameters,p=> p*2);
    Asynchrous.ContinueWithAsync(operators,Console.WriteLine,"执行完成");
    }
    
  • 每一回执行完继续执行
    唯恐有时候大家须求遍历多个集合,每种成分处理完了后大家须要输出XX处理完了

    public void Test
    {
    int[] parameters = {1,2,3,4,5};
    var operators = Asynchronous.Foreach(parameters,p=> p*2);
    Asynchronous.Foreach(operators,o=>{
        o.ContinueWithAsync(()={
            //每个元素执行完时执行
            if(o.Exception != null)
            {
                //之前执行时产生未处理的异常,这里可以捕获到  
            }
        });
    });
    }
    
  • 能够兑现链式异步操作

    public void Chain()
    {
    Asynchronous.Invoke(Console.WriteLine,1)
    .ContinueWithAsync(Console.WriteLine,2)
    .ContinueWithAsync(Console.WriteLine,3)
    }
    

    那般会按步骤输出一,2,叁

    结束语

    上述只是列出了一些重载方法,其余重载方法唯有正是加参数,本质实际上是如出一辙的,具体能够已交付至github。笔者还包裹了for方法,不过感觉没什么用,而且也从不曾用到过,那里不再提
    由此以上的卷入,已经能不负众望日常超越四分之贰的操作,调用依然比较便利的。

正文揭穿至作业部落

等待Task

在ThreadPool内置的措施中无法兑现的等候,在Task中能够很简短的兑现了:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace MultiThread
{
    class ThreadTest
    {
        static void Main()
        {
            var t1 = Task.Run(() => Go(null));
            var t2 = Task.Run(() => Go(123));
            Task.WaitAll(t1, t2);//等待所有Task结束
            //Task.WaitAny(t1, t2);//等待任意Task结束
        }

        static void Go(object data)   // data will be null with the first call.
        {
            Thread.Sleep(5000);
            Console.WriteLine("Hello from the thread pool! " + data);
        }
    }
}

  

注意:

当您调用七个Wait方法时,当前的线程会被堵塞,直到Task重返。不过如果Task还未曾被实施,那年系统大概会用当前的线程来施行调用Task,而不是新建叁个,那样就不必要再一次创制二个线程,并且阻塞当前线程。那种做法节省了创办新线程的开销,也防止了有些线程的切换。不过也有缺点,当前线程要是和被调用的Task同时想要获得一个lock,就会造成死锁。

  List<String> collected = Stream.of("a", "b").collect(Collectors.toList());


   Set<String> names=new HashSet<>();
    names=artists.stream().map(u->u.getName()).collect(Collectors.toSet());

Task万分处理

当等待1个Task达成的时候(调用Wait也许恐怕访问Result属性的时候),Task职分中未有处理的老大会被封装成AggregateException重新抛出,InnerExceptions属性封装了一1Task未有处理的那多少个。

using System;
using System.Threading.Tasks;

namespace MultiThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int x = 0;
            Task<int> calc = Task.Factory.StartNew(() => 7 / x);
            try
            {
                Console.WriteLine(calc.Result);
            }
            catch (AggregateException aex)
            {
                Console.Write(aex.InnerException.Message);  // Attempted to divide by 0
            }
        }
    }
}

  

对此有父亲和儿子关系的Task,子职责未处理的不得了会逐层传递到父Task,并且最终打包在AggregateException中。

using System;
using System.Threading.Tasks;

namespace MultiThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            TaskCreationOptions atp = TaskCreationOptions.AttachedToParent;
            var parent = Task.Factory.StartNew(() =>
            {
                Task.Factory.StartNew(() =>   // Child
                {
                    Task.Factory.StartNew(() => { throw null; }, atp);   // Grandchild
                }, atp);
            });

            // The following call throws a NullReferenceException (wrapped
            // in nested AggregateExceptions):
            parent.Wait();
        }
    }
}

  

  • #### 2.map

  • 将1种档次的值转换为此外1系列型的值。

  • 代码:将List 转换成List

取消Task

若果想要帮助撤消职责,那么在创设Task的时候,需求传入贰个CancellationTokenSouce

以身作则代码:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace MultiThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var cancelSource = new CancellationTokenSource();
            CancellationToken token = cancelSource.Token;

            Task task = Task.Factory.StartNew(() =>
            {
                // Do some stuff...
                token.ThrowIfCancellationRequested();  // Check for cancellation request
                // Do some stuff...
            }, token);
            cancelSource.Cancel();

            try
            {
                task.Wait();
            }
            catch (AggregateException ex)
            {
                if (ex.InnerException is OperationCanceledException)
                    Console.Write("Task canceled!");
            }

            Console.ReadLine();
        }
    }
}

  

任务的连日实施

 List<String> collected = Stream.of("a", "b").collect(Collectors.toList());

  List<Integer> figure = collected.stream().map(s -> {
            Integer i;
            switch (s) {
                case "a":
                    i = 1;
                    break;
                case "b":
                    i = 2;
                    break;
                default:
                    i = -1;
                    break;
            }
            return i;
        }).collect(Collectors.toList());

Continuations

职责调度也是相近的要求,Task帮助一个职责实现之后执行另2个任务。

            Task task1 = Task.Factory.StartNew(() => Console.Write("antecedant.."));
            Task task2 = task1.ContinueWith(task =>Console.Write("..continuation"));

  

  • #### 3.filter(类似于C#的Where)

  • 遍历数据并检讨当中的要素是或不是合乎给出的表达式的成分

  • #### 4.flatMap(类似C# AddRange)

  • 将八个Stream连接成一个Stream,那时候不是用新值取代Stream的值,与map有所不相同,那是再也生成四个Stream对象取而代之

Continuations 和Task<TResult>

Task也有带重返值的重载,示例代码如下:

            Task.Factory.StartNew<int>(() => 8)
                .ContinueWith(ant => ant.Result * 2)
                .ContinueWith(ant => Math.Sqrt(ant.Result))
                .ContinueWith(ant => Console.WriteLine(ant.Result));   // output 4

  

子任务

后面提到了,当您等待2个任务的时候,同时须要静观其变它的子职责成功。

下边代码演示了带子职务的Task:

using System;
using System.Threading.Tasks;
using System.Threading;

namespace MultiThreadTest
{
    class Program
    {
        public static void Main(string[] args)
        {
            Task<int[]> parentTask = Task.Factory.StartNew(() =>
            {
                int[] results = new int[3];

                Task t1 = new Task(() => { Thread.Sleep(3000); results[0] = 0; }, TaskCreationOptions.AttachedToParent);
                Task t2 = new Task(() => { Thread.Sleep(3000); results[1] = 1; }, TaskCreationOptions.AttachedToParent);
                Task t3 = new Task(() => { Thread.Sleep(3000); results[2] = 2; }, TaskCreationOptions.AttachedToParent);

                t1.Start();
                t2.Start();
                t3.Start();

                return results;
            });

            Task finalTask = parentTask.ContinueWith(parent =>
            {
                foreach (int result in parent.Result)
                {
                    Console.WriteLine(result);
                }
            });

            finalTask.Wait();
            Console.ReadLine();
        }
    }
}

  

那段代码的出口结果是: 一,二,三

FinalTask会等待全部子Task甘休后再实施。

   List<Integer> a=new ArrayList<>();
        a.add(1);
        a.add(2);
        List<Integer> b=new ArrayList<>();
        b.add(3);
        b.add(4);
        List<Integer> figures=Stream.of(a,b).flatMap(u->u.stream()).collect(Collectors.toList());
        figures.forEach(f->System.out.println(f));

TaskFactory

关于TaskFactory,上边的事例中大家应用了System.Threading.Tasks
.Task.Factory属性来快捷的开创Task。当然你也足以协调创设TaskFactory,你能够钦命自身的TaskCreationOptions,TaskContinuationOptions来驱动通过你的Factory创立的Task暗许行为不相同。

.Net中有部分默许的创导Task的点子,由于TaskFactory创立Task的暗中同意行为不一样只怕会导致部分不不难觉察的标题。

如在.NET 肆.5中,Task插手了2个Run的静态方法:

Task.Run(someAction);

要是您用这几个主意代替上边例子中的Task.Factory.StartNew,就不能够获得不错的结果。原因是Task.Run创制Task的行事暗许是暗许是拒绝添加子职分的。上边包车型客车代码等价于:

    Task.Factory.StartNew(someAction, CancellationToken.None,
TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

你也能够创制具有友好暗中同意行为的TaskFactory。

 

不管ThreadPool也好,大概Task,微软都以在想进办法来贯彻线程的重用,来节省不停的创办销毁线程带来的付出。线程池内部的落实或者在不一样版本中有分歧的体制。假如只怕的话,使用线程池来治本线程依然是提出的选料。

 

我们主要介绍了一下Task的骨干用法,在大家编制程序进度中,有壹些行使Task来提高程序品质的场所往往是很相像的,微软为了简化编制程序,在System.Threading.Tasks.Parallel中封装了1层层的并行类,内部也是由此Task来贯彻的。

  • #### 5.max及min

  • 求最大值和最小值

  • 此时max及min接受的是Comparator<? super T> comparator

Parallel的For,Foreach,Invoke 方法

 

在编制程序进程中,大家平常会用到循环语句:

 

            for (int i = 0; i < 10; i++)
            {
                DoSomeWork(i);
            }

  

若是循环进程中的工作得以是并行的话,那么大家能够用如下语句:

 

            Parallel.For(0, 10, i => DoSomeWork(i));

  

我们也时不时会动用Foreach来遍历有些集合:

 

            foreach (var item in collection)
            {
                DoSomeWork(item);
            }

  

1经咱们用一个线程池来推行里面包车型地铁天职,那么我们得以写成:

 

            Parallel.ForEach(collection, item => DoSomeWork(item));

  

末段,假如你想相互的进行多少个例外的措施,你能够:

 

            Parallel.Invoke(Method1, Method2, Method3);

  

比方您看下后台的完结,你会发觉主题都以依据Task的线程池,当然你也得以透过手动成立3个Task集合,然后等待全数的任务完结来落到实处均等的作用。上边的Parallel.For和Parallel.Forach方法并不以为那你能够寻找你代码里面装有用到For和Foreach方法,并且替代他们,因为每一个任务都会分配四个信托,并且在线程池里推行,要是委托里面的职责是线程不安全的,你或者还须求lock来保险线程安全,使用lock本人就会促成品质上的损耗。借使每3个职责都以索要长日子执行并且线程安全的,Parallel会给你带来不利的属性提高。对于短任务,大概线程不安全的义务,你须求权衡下,你是不是确实须求动用Parallel。

作者:独上高楼
出处:http://www.cnblogs.com/myprogram/
正文版权归小编和搜狐共有,欢迎转发,但未经小编同意必须保留此段证明,且在篇章页面显明地方给出原来的小说连接,不然保留追究法律权利的任务。

 Integer m=figures.stream().max(Comparator.comparing(u->u)).get();
        System.out.println(m);
  • #### 6.reduce

  • 从1组值中生成一个值。比如在壹组List将富有因素依次相加

 Integer s = figures.stream().reduce((x, y) -> x + y).get();
  • ### 四、总结

  • 一.在编写制定项目代码时候,多选择在那之中迭代,防止太多的外部冗余,简化代码

  • 二.将拉姆da表明式与Stream方法结合起来,能够做到很多操作

相关文章