zoukankan      html  css  js  c++  java
  • 线程基础和异步执行计算限制

    线程基础

    进程是一个应用程序实例要使用资源的集合。无法与windows内核的数据和代码沟通,维持系统的健壮性。

    线程是一个虚拟的cpu,防止和其他的程序混在一起,最终是操作系统瘫痪掉。

    线程的要素:线程内核对象、线程环境块、用户模式栈、内核模式栈、Dll线程链接和线程分离通知。

    A、线程内核对象:每个线程初始化时都带有这种数据结构。数据结构包括描述线程的属性和线程上下文(上下文是内存块,主要包含CPU的寄存器集合,寄存器是cpu的组成部分,可以用来暂存指令,数据和地址。)

    B、线程环境块:是在用户模式中分配和初始化的内存块(内存是是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据)

    C、用户模式栈:主要存储传给方法的变量和实参。还包括一个地址,知道方法执行完从哪里继续。

    D、内核模式栈:如果程序需要和操作系统内核打交道的话,需要把用户模式栈中的数据传到内核模式栈,经过验证后,让os进行相关操作。

    E、dll线程链接和线程分离通知,一种标志。

    时间片的切换让操作系统可以一个程序进入了死循环,然后可以继续执行其他程序,而不需要重启操作系统,但切换影响效率。

    clr使用的是windows的线程处理能力。

    Console.WriteLine("Main thread: starting a dedicated thread " +
               "to do an asynchronous operation");
            Thread dedicatedThread = new Thread(ComputeBoundOp);
            dedicatedThread.Start(5);
    
            Console.WriteLine("Main thread: Doing other work here...");
            //Thread.Sleep(10000);     // Simulating other work (10 seconds)
    
            dedicatedThread.Join();  // 等待dedicatedThread线程执行完才会继续下面的线程
            Console.WriteLine("haiziguo");
            Console.ReadLine();
        }
    
        // This method's signature must match the ParametizedThreadStart delegate
        private static void ComputeBoundOp(Object state)
        {
            // This method is executed by a thread pool thread
    
            Console.WriteLine("In ComputeBoundOp: state={0}", state);
            Thread.Sleep(10000);  // Simulates other work (1 second)
    
            // When this method returns, the dedicated thread dies
        }

    所有的前台线程停止,后台线程必须停止,且不会抛出异常。

    计算限制异步编程——线程池

    CLR包含了代码来管理他自己的线程池。一个CLR包括一个线程池。

    默认线程池创建的线程都是后台线程。

    线程池将自己的线程划分为工作者线程和IO线程。

    IO线程用于通知你的代码一个异步IO限制操作已经完成。

    异步编程模式发出IO请求,比如访问文件、网络服务器、数据库、web服务、其他硬件设备。

    线程上下文(CallContext)通常是在主线程流向辅助线程,以使主线程和辅助线程的各种权限一致,当然可以阻止流动。

    CallContext.LogicalSetData("Name", "Jeffrey");
    
            // Initiate some work to be done by a thread pool thread
            // The thread pool thread can access the logical call context data 
            ThreadPool.QueueUserWorkItem(
               state => Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name")));
    
    
            // Suppress the flowing of the Main thread’s execution context
            ExecutionContext.SuppressFlow();
    
            // Initiate some work to be done by a thread pool thread
            // The thread pool thread can NOT access the logical call context data
            ThreadPool.QueueUserWorkItem(
               state => Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name")));

    取消线程操作:

    private static void CancellingAWorkItem()
        {
            CancellationTokenSource cts = new CancellationTokenSource();
    
            // Pass the CancellationToken and the number-to-count-to into the operation
            ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
    
            Console.WriteLine("Press <Enter> to cancel the operation.");
            Console.ReadLine();
            cts.Cancel();  // If Count returned already, Cancel has no effect on it
            // Cancel returns immediately, and the method continues running here...
    
            Console.ReadLine();  // For testing purposes
        }
    
        private static void Count(CancellationToken token, Int32 countTo)
        {
            for (Int32 count = 0; count < countTo; count++)
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("Count is cancelled");
                    break; // Exit the loop to stop the operation
                }
    
                Console.WriteLine(count);
                Thread.Sleep(200);   // For demo, waste some time
            }
            Console.WriteLine("Count is done");
        }

    如果禁止被取消时,可以传入一个Token的静态变量。可以使用CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);来创建多个,一个取消时,LinkedTokenSource就取消。可以创建多个。

    计算限制异步编程——任务

    线程池的QueueUserWorkItem没有返回值,不知道什么时间结束。下面给出含有返回值的Task代码

    Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 10000);
    
            // You can start the task sometime later
            t.Start();
    
            // Optionally, you can explicitly wait for the task to complete
            t.Wait(); // FYI: Overloads exist accepting a timeout/CancellationToken
    
    
            // Get the result (the Result property internally calls Wait) 
            Console.WriteLine("The sum is: " + t.Result);   // An Int32 value

    Task条用Wait的两种情况:a.已经开始Start,调用Task的线程阻塞,直到Task完成为止;b.没有start,调用Task线程不会出现阻塞,而是使用需要等Task完成后才继续线程原来正在执行的操作。可以理解为一个是“线程阻塞”,一个是“步骤阻塞”。

    当Task出现异常的话,只有在使用wait和result时才能发现。

    下面代码演示如何判断取消Task

    private static Int32 Sum(CancellationToken ct, Int32 n)
        {
            Int32 sum = 0;
            for (; n > 0; n--)
            {
    
                // The following line throws OperationCanceledException when Cancel 
                // is called on the CancellationTokenSource referred to by the token
                //如果使用CancellationToken的取消,那么就抛出异常,
                //判断是否是指定的异常,来判断是否是取消了任务
                ct.ThrowIfCancellationRequested();
              Console.WriteLine(n);
                //Thread.Sleep(0);   // Simulate taking a long time
                checked { sum += n; }
            }
            return sum;
        }
    private static void Cancel()
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            Task<Int32> t = new Task<Int32>(() => Sum(cts.Token, 10000), cts.Token);
    
            t.Start();
    
            // Sometime later, cancel the CancellationTokenSource to cancel the Task
            cts.Cancel();
    
            try
            {
                // If the task got canceled, Result will throw an AggregateException
                Console.WriteLine("The sum is: " + t.Result);   // An Int32 value
            }
            catch (AggregateException ae)
            {
                // Consider any OperationCanceledException objects as handled. 
                // Any other exceptions cause a new AggregateException containing 
                // only the unhandled exceptions to be thrown          
                ae.Handle(e => e is OperationCanceledException);
    
                // If all the exceptions were handled, the following executes
                Console.WriteLine("Sum was canceled");
            }
        }

    一个任务完成后继续另外一个任务,继续的任务会自动开始

    //继续的任务会自动开始
            // Create Task, defer starting it, continue with another task
            Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 10000);
    
            // You can start the task sometime later
            t.Start();
    
            // ContinueWith returns a Task but you usually don't care
            Task cwt = t.ContinueWith(task => Console.WriteLine("The sum is: " + task.Result));
            //cwt.Start();

    执行定时计算限制操作

    //
            // 摘要:
            //     用 32 位无符号整数来度量时间间隔,以初始化 Timer 类的新实例。
            //
            // 参数:
            //   callback:
            //     一个 System.Threading.TimerCallback 委托,表示要执行的方法。
            //
            //   state:
            //     一个包含回调方法要使用的信息的对象,或者为 null。
            //
            //   dueTime:
            //     调用 callback 之前延迟的时间量(以毫秒为单位)。 指定 System.Threading.Timeout.Infinite 可防止启动计时器。
            //     指定零 (0) 可立即启动计时器。
            //
            //   period:
            //     调用 callback 的时间间隔(以毫秒为单位)。 指定 System.Threading.Timeout.Infinite 可以禁用定期终止。
            //
            // 异常:
            //   System.ArgumentOutOfRangeException:
            //     dueTime 或 period 参数为负,并且不等于 System.Threading.Timeout.Infinite。
            //
            //   System.ArgumentNullException:
            //     callback 参数为 null。
            [CLSCompliant(false)]
            [SecuritySafeCritical]
            public Timer(TimerCallback callback, object state, uint dueTime, uint period);

    线程池为所有的Timer对象只使用一个线程。当第一个对象还没有执行完,下一个就开始了,肯定会出现重复执行timer的事件了,为了防止这样事件的放生,可以如下

    Timer timer = new Timer((s) =>
            {
                for (int i = 0; i < 1000; i++)
                {
                    Console.WriteLine(i);
                }
            }, null, 0,Timeout.Infinite);
            Thread.Sleep(5000);
            timer.Change(0, Timeout.Infinite);

    Timeout.Infinite, 然后再使用Change。

  • 相关阅读:
    MySQL事务知识要点(一)
    MySQL 安全体系知识要点
    MySQL 安全性知识要点
    #翻译#通往SQL Server安全级别2的阶梯:身份验证; 唐•吉利; 原文链接:Stairway to SQL Server Security Level 2: Authentication http://www.sqlservercentral.com/articles/Stairway+Series/109975/
    SQL子查询&视图&更新&删除思维导图-误点难点(附示例代码)
    #翻译#通往t
    香港中文大学-人脸识别进展-2014-06
    NotesMITLinearAlgebra
    Notes Berkerly Statistics 2.1X Week4
    Notes on Brain Study
  • 原文地址:https://www.cnblogs.com/lzhp/p/3420934.html
Copyright © 2011-2022 走看看