zoukankan      html  css  js  c++  java
  • 多线程学习进程

    第一章,线程

    什么是单线程?

    在一个程序中只允许一个主线程(cpu分配的)来执行不同的任务。简而言之就是一个任务一个人独干,在没有干完之前不回去做其他的,直到当前的任务做完。会导致“假死现象”。

    例子:我们平时定义的方法及实现,然后普通调用。就是属于单线程操作。

    什么是线程?

    线程是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。

    什么是多线程?

    多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

    文字总结:

    在C#中我们开启一个应用程序就是打开了一个进程,这个进程中包括一个主线程。我们可以在此基础上在增加自己写的单个或多个线程,来执行我们想要完成的任务。

    在Thread线程类中我们常用到的一样方法:

    • Start():启动线程;
    • Sleep(int):静态方法,暂停当前线程指定的毫秒数;
    • Abort():通常使用该方法来终止一个线程;之后不能使用Start():启动线程。会报错误。
    • Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复;
    • Resume():恢复被Suspend()方法挂起的线程的执行。

      在C#中开启一个线程,来执行我们所写的方法。主要是通过ThreadStart代理委托来实现。学习代码如下:

    1.无参数的线程

     class Program
            {
                static void Main(string[] args)
                {
                    OneThread();//方法调用
                }
                static void OneThread()
                {
    //创建线程去执行这个方法 Thread objThread
    = new Thread(ThreadMethod); objThread .IsBackground = true; //我们创建的线程属于前台线程,设需置当前子线程为后台线程,为后台线程意味着,主线程(前台线程)关闭后,其他子线程都同时关闭 objThread .Start();//标记这个线程准备就绪了,可以随时被执行。具体什么什时候执行这个线程有cpu决定。 Console.ReadLine(); } static void ThreadMethod()//无参数 { for (int i = 0; i < 10; i++) { Console.WriteLine("我是线程调用的!!!"); } } }

    线程分为:前台线程和后台线程。另见前台线程和后台线程总结。

    知识点:Control.CheckForIllegalCrossThreadCalls = false;取消跨线程的访问 让可以跨线程访问Control 是基类

    小知识:跨线程访问控件  使用Invoke()方法

    首先在当前的函数中判断是否跨线程使用InvokeRequired 做判断。

    InvokeRequired 是做判断的,判断this的线程和调用这个方法(函数)的线程是不是同一个线程。如果是True,则调用invoke(new Action<>(x=>{}),第二个参数)方法

    在需要使用跨线程时在.net环境下会出现错误,需要取消跨线程的访问。在关闭某个线程时可能会出现DIspose错误这是因为主线程已关闭而新建的线程还在运行,所以会出现错误

    解决方法为:通过判断当前的新建线程是否为null

    例如:

    Thread th=new Thread(线程需要执行的方法);

    if(th!=null)

    {

    th.Abort();  //结束这个线程

    }

     2.带参数的多线程

      class Program
            {
                static void Main(string[] args)
                {
                    OneThread();
                }
    
                static void OneThread()
                {
    
                object ThreadParameter = "P";
                Thread ThreadB = new Thread(new ParameterizedThreadStart(ThreadMethodParameter));
                threadB.IsBackground = true;// 设置当前子线程为后台线程,为后台线程意味着,主线程关闭后,其他子线程都同时关闭
                threadB.Start(ThreadParameter);
    
                Console.WriteLine("Main Write:M");
    
                Console.ReadLine();
                }
            
                /// <summary>
                /// 带参数线程
                /// </summary>
                /// <param name="Parameter">只能定义一个object参数,因为委托ParameterizedThreadStart为单参数object类型</param>
                static void ThreadMethodParameter(object Parameter)//带参数的线程
                {
                    for (int j = 0; j < 10; j++)
                    {
                        Console.WriteLine("我后面的Parameter是参数!" + Parameter);
                    }
                }
    
            }

    注:public delegate void ParameterizedThreadStart(object obj);//委托ParameterizedThreadStart为单参数object类型

    在代理里分别开启两个线程。

    第一个线程objThread 没带参数,线程运行时去执行ThreadMethod()方法.

    第二个线程ThreadB带上一个Object参数,通过ParameterizedThreadStart委托去执行ThreadMethodParameter(object Parameter)方法.此线程在调用Start()时传入所需参数。

    (写代码时我在想为什么带参数线程只能传一个object参数?看了代码才知道ParameterizedThreadStart只有一个参数没有重载)。

     Thread类:表示托管线程,每个Thread对象都代表一个托管线程,每个托管线程都对应一个函数。

    多线程的启动:

    第一种: Start():启动线程;

    第二种:线程池:

        (1)ThreadPool.QueuUserWorkItem(t=>{}) 有参数无返回值

      (2)ThreadPool.QueuUserWorkItem(t=>t.Tostring(),{}) 线程池的线程等待:

    using(ManualResetEvent  m=new ManualResetEvent (false));//false不初始化等着

    {

    ThreadPool.QueuUserWorkItem(t=>{

    ///需要执行的代码

    m.Set();//执行完通知

    }) ;

    m.WaitOne()

    }

    第三种:Task   推荐使用

    首先,TaskFactory task=new TaskFactory();//初始化

    task.StartNew(()=>{});//启动线程   StartNew(Action action)

      Task是基于线程池的,只是API被强化

         时间统计:

       List<Task>   taskList=new List<Task>();

               (1)给taskList添加启动是线程          taskList.Add(task.StartNew(()=>{}););

                ( 2)统计时间   Task.WaitAll(taskList.ToArray());

     continueWhenAll(taskList.TOArray(),{}) //结束当前所用任务线程后,会重新自动启用新线程(热线程)

    continueWhenAny(taskList.TOArray(),{})//某个任务完成后直接执行

  • 相关阅读:
    面试:div水平垂直居中方案--img自适应
    面试:call、apply、bind原理以及自己手写简易模式
    面试之:判断js类型的方式总结
    git的项目完整操作
    vue3.x版本新建项目相关知识和注意事项
    面试常问平时项目中【Date】的常用操作方法总结
    面试常问平时项目中【Math】的常用操作方法总结
    面试常问平时项目中数组【Array】的常用操作方法总结
    面试常问平时用的对象【Object】的创建方式和常用的对象方法总结
    优化无限列表性能vue-virtual-scroll-list【测试90w条数据】
  • 原文地址:https://www.cnblogs.com/wfaceboss/p/6373643.html
Copyright © 2011-2022 走看看