使用多线程可以利用多核CPU的计算能力,可以提供更好的程序响应能力,但是每个线程都有开销,需要注意控制线程的数量。

1. System.Threading.Thread

使用多线程最直接的是使用System.Threading.Thread。回调函数可以接受一个参数、或者不接受参数,没有返回值。

Thread t = new Thread(Echo);
t.Start("test");

t.Join();

t = new Thread(DoSomeThing);
t.Start();

private static void Echo(object obj)
{
    Console.WriteLine(obj);
    Thread.Sleep(100);
}

private static void DoSomeThing()
{
    Console.WriteLine("DoSomeThing, threadid={0}", Thread.CurrentThread.ManagedThreadId);
    Thread.Sleep(100);
}

2. 线程池

创建和销毁线程需要大量的时间,太多的线程还会消耗大量的内存。使用线程池可以重用线程,方便线程的管理。每个CLR有一个线程池,里面的线程分为Worker和IO线程。

回调函数只能是接受一个参数的函数,没有返回值。

ThreadPool.QueueUserWorkItem(Echo, "test2");

3. 取消

使用CancellationTokenSource和对应的CancellationToken实现协作式取消,CancellationToken是结构类型,包含对CancellationTokenSource的引用。CancellationTokenSource封装了数据,CancellationToken封装了操作。每个线程都有自己的Token,但是访问同一个Source,通过改变Source的状态,可以通知所有监测Token的线程。

CancellationTokenSource cts1 = new CancellationTokenSource();
cts1.Token.Register(
    () =>
        {
            Console.WriteLine("cts1 canceled, threadid={0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(100);
        });
CancellationTokenSource cts2 = new CancellationTokenSource();
cts2.Token.Register(
    () =>
        {
            Console.WriteLine("cts2 canceled, threadid={0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(100);
        });
var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
linkedCts.Token.Register(
    () =>
        {
            Console.WriteLine("linkedCts cancled, threadid={0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(100);
        });

Task.Factory.StartNew(
    () =>
        {
            Thread.Sleep(100);
            if (cts1.Token.IsCancellationRequested)
            {
                Console.WriteLine("Canceled. threadid={0}", Thread.CurrentThread.ManagedThreadId);
            }
        });

cts1.Cancel();

4. Task

线程池的任务没有办法知道状态,也没有返回值。Task建立在线程池基础上,提供了这些功能。

var t = new Task<int>(sum, 20);
t.Start();
Console.WriteLine(t.Result);

Task用法的一个例子。包括TaskFactory,Cancel,ContinueWith

Task parent = new Task(
    () =>
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            TaskFactory<int> tf = new TaskFactory<int>(
                cts.Token,
                TaskCreationOptions.AttachedToParent,
                TaskContinuationOptions.ExecuteSynchronously,
                TaskScheduler.Default);
            var childTasks = new[]
                                 {
                                     tf.StartNew(() => sum(cts.Token, 1000)),
                                     tf.StartNew(() => sum(cts.Token, 2000)),
                                     tf.StartNew(() => sum(cts.Token, int.MaxValue))
                                 };

for (int i = 0; i < childTasks.Length; i++)
            {
                childTasks[i].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);
            }

tf.ContinueWhenAll(
                childTasks,
                completedTasks =>
                completedTasks.Where(t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result),
                CancellationToken.None)
                .ContinueWith(
                    t => Console.WriteLine("The max is {0}", t.Result),
                    TaskContinuationOptions.ExecuteSynchronously);
        });

parent.ContinueWith(
    p =>
        {
            StringBuilder sb =
                new StringBuilder(
                    string.Format("Following exception(s) occurred. {0}", Environment.NewLine));
            foreach (var e in p.Exception.Flatten().InnerExceptions)
            {
                sb.AppendLine(string.Format(" {0}: {1}", e.GetType(), e.Message));
            }
            Console.WriteLine(sb.ToString());

},
    TaskContinuationOptions.OnlyOnFaulted);

parent.Start();

5. APM(Aync Programming Model)

.NET并行编程 - 并行方式的更多相关文章

  1. 四、并行编程 - 并行LINQ(PLINQ) 的使用。AsParallel

    用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算 一.AsParallel(并行化) 就是在集合后加个AsParallel(). 例如: , ); == ); ...

  2. .Net并行编程

    1.什么是线程?线程和进程的区别是什么? 线程是程序执行的最小单元. 区别: 进程是操作系统进行资源处理和分配的最小单位,而一个进程可以包含多个线程,并共享进程的资源. 2.什么是多线程?为什么设计多 ...

  3. 三、并行编程 - Task同步机制。TreadLocal类、Lock、Interlocked、Synchronization、ConcurrentQueue以及Barrier等

    在并行计算中,不可避免的会碰到多个任务共享变量,实例,集合.虽然task自带了两个方法:task.ContinueWith()和Task.Factory.ContinueWhenAll()来实现任务串 ...

  4. 二、并行编程 - Task任务

    任务,基于线程池.其使我们对并行编程变得更简单,且不用关心底层是怎么实现的.System.Threading.Tasks.Task类是Task Programming Library(TPL)中最核心 ...

  5. 一、并行编程 - 数据并行 System.Threading.Tasks.Parallel 类

    一.并行概念 1.并行编程 在.NET 4中的并行编程是依赖Task Parallel Library(后面简称为TPL) 实现的.在TPL中,最基本的执行单元是task(中文可以理解为"任 ...

  6. Java中的函数式编程(八)流Stream并行编程

    写在前面 在本系列文章的第一篇,我们提到了函数式编程的优点之一是"易于并发编程". Java作为一个多线程的语言,它通过 Stream 来提供了并发编程的便利性. 题外话: 严格来 ...

  7. .Net中的并行编程-2.ConcurrentStack的实现与分析

    在上篇文章<.net中的并行编程-1.基础知识>中列出了在.net进行多核或并行编程中需要的基础知识,今天就来分析在基础知识树中一个比较简单常用的并发数据结构--.net类库中无锁栈的实现 ...

  8. .Net中的并行编程-3.ConcurrentQueue实现与分析

    在上文<.Net中的并行编程-2.ConcurrentQueue的实现与分析> 中解释了无锁的相关概念,无独有偶BCL提供的ConcurrentQueue也是基于原子操作实现, 由于Con ...

  9. C#~异步编程再续~大叔所理解的并行编程(Task&Parallel)

    返回目录 并行这个概念出自.net4.5,它被封装在System.Threading.Tasks命名空间里,主要提供一些线程,异步的方法,或者说它是对之前Thread进行的二次封装,为的是让开发人员更 ...

随机推荐

  1. SAPCAR 压缩解压软件的使用方法

    SAPCAR 是 SAP 公司使用的压缩解压软件,从 SAP 网站下载的补丁包和小型软件基本都是扩展名为 car 或 sar 的,它们都可以用 SAPCAR 来解压.下面是它的使用说明: 用法: 创建 ...

  2. Life of a triangle - NVIDIA's logical pipeline

    Home GameWorks Blog Life of a triangle - NVIDIA's logical pipeline   Life of a triangle - NVIDIA's l ...

  3. 转载:Android横屏竖屏切换的问题

    一.禁止横竖屏转换 Android横竖屏切换在手机开发中比较常见,很多软件在开发过程中为了避免横竖屏切换时引发不必要的麻烦,通常禁止掉横竖屏的切换, 通过在AndroidManifest.xml中设置 ...

  4. QT显示歌词渐变

    central = new QWidget(this); setCentralWidget(central); central->setAutoFillBackground(true); cen ...

  5. forEach遍历数组实例

    forEach()取出数组中2的倍数和3的倍数的数 //for IE if(!Array.prototype.forEach){ Array.prototype.forEach = function( ...

  6. 使用MySQL制作SNP146数据库

    SNP数据(txt)文件可以在此下载:http://hgdownload.cse.ucsc.edu/goldenPath/hg19/database/ 下载.解压data之后,启动MySQL serv ...

  7. MySQL集群在断网后再启动报"Unable to start missing node group"问题处理

    总所周知,MySQL集群又名ndb cluster,而ndb就是network based database的简称,数据库节点之间依靠网络来通信和保证数据分块间的一致性.今天由于机房交换机损坏,导致集 ...

  8. U盘格式转换

    有一次想把5G的文件拷到U盘里面,悲催的发现拷不进去,文件过大...... 硬盘格式:NTFS 把自己的U盘也改了格式后,就可以了

  9. MySql 中游标,事务,终止存储过程方法总结

    最近在项目开发中,有段逻辑处理,需要在网站,app,后台分别运行,这样给后期的维护带来了很大的不方便,容易遗漏app端或者后台,所以讲java代码转换成存储过程,把逻辑处理写在了mysql端,其中遇到 ...

  10. 《Android深度探索HAL与驱动开发》第四章阅读心得

     Android源代码包含了很多内容,可以实现拍照.计算机.日历.相册.拨号器等功能.配置Android源代码下载环境需要如下几步: (1)创建一个用于存放下载脚本文件的目录:  (2)下载repo脚 ...