zoukankan      html  css  js  c++  java
  • .NET并行编程

    使用多线程可以利用多核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)

  • 相关阅读:
    SpringData JPA接口总结
    使用allatori混淆代码
    Oracle查看表空间大小
    Mac常用命令
    Web.config或App.config下section
    ansi、unicode、UCS、UTF等概念(转)
    强名称程序集与GAC
    指针和引用的区别(转)
    .NET程序员应该知道些什么(转)
    dispose,null和close的区别
  • 原文地址:https://www.cnblogs.com/lingshf/p/5306848.html
Copyright © 2011-2022 走看看