多线程学习进程

第一章,线程

什么是单线程?

在一个程序中只允许一个主线程(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(),{})//某个任务完成后直接执行

原文地址:https://www.cnblogs.com/wfaceboss/p/6373643.html