c#学习笔记(进程和线程)

       一个C#程序起始于一个由】C【】LR与操作系统创建的一个单线程,并且可以通过创建其他的线程来实现多线程编程。

一、基本概念

1、进程:进程是系统资源分配和资源调度的基本单位,每个独立执行的程序在系统中都是一个进程。如qq、word都是一个进程。

2、线程:线程是进程中的执行流程,一个进程中可以包含多个线程,每个线程也可以得到一个小段程序的执行时间。

3、线程调度:

        多线程是被CLR内部的线程调度所管理的,这是CLR代表操作系统的一个典型性功能。线程调度能够保证所有的活动的线程都被安排了可行的操作时间,并且线程的等待和挂起并不消耗CPU的资源。在单处理器的计算机上,一个线程调度操控着时隙表,使每个活动线程间的操作能够快速地转换。在一个多处理器计算机上,多线程将在最短时间内被执行,因为不同的线程将在不同的处理器上运行,但是它还是存在特定的时间片。

4、线程和进程的关系

    在一个单独的应用程序中,所有的线程都被一个进程以一定的逻辑包含着。进程也是依赖于时间片的概念。

     进程完全独立于其他进程的,而线程则与其他同一应用程序中的线程共享存储区。

二、线程管理

1、启动线程

Thread t1=new Thread(方法名);//创建一个线程
t1.Start();//启动该线程

2、线程休眠

sleep在给出的时间区间内阻断。

多线程中,为了使某个线程暂停一段时间

Thread.Sleep(5000);//当前线程暂停5s

3、合并线程

join等待另一个线程来结束。

join方法用于把指定的线程合并到当前线程。如果一个线程T1在执行过程中需要等待另个一个线程T2结束后才能继续执行。

Thread t1=new Thread(port1);//创建一个线程t1
t1.Start();//启动该线程

Thread t2=new Thread(port2);//创建一个线程t2
t2.Start();//启动该线程

void port1()
{
     t2.Join();//中断线程1,执行线程2,等待线程2终止,线程1才能继续执行
}

void port1()
{

}

 4、线程终止

if(t1.ThreadState==ThreadState.Running)//判断线程是否在执行
{
   t1.Abort();//终止线程
}

 

5、线程的优先级

在多任务操作系统中,每个线程都会得到一小段CPU时间片进行执行,在时间结束时,将轮换另一个线程进入执行状态,这时会选择与当前线程优先级相同的进程进行执行。

如优先级下   :

线程5:线程A和线程B 

线程4:线程C

...

线程1:线程D

执行过程:优先级为5的线程A首先的得到CPU时间片,当改时间结束后,轮换到与线程A相同优先级的线程B,当线程B的运行时间结束后,会继续轮换到线程A,当线程A和线程B 都执行完后,才会轮到执行线程B.

Thread t1=new Thread(port1);//创建一个线程t1
t1.Priority= ThreadPriority.Lowest;//设置优先级最低
t1.Start();//启动该线程

Thread t2=new Thread(port2);//创建一个线程t2
t2.Priority= ThreadPriority.Highest;//设置优先级最高
t2.Start();//启动该线程

6、线程同步机制

为了防止多线程中,发送两个线程抢占资源的问题,引入线程同步机制,线性同步指并发线程高效、有序的访问执行,所谓同步,是指某一时刻只有一个线程可以访问资源,只有资源所拥有者放弃了代码或资源的拥有权时,其他线程才可以使用这些资源。

(1)使用lock关键字实现线程同步

lock关键字可以用来确保代码完成运行,而不被其它线程中断。

Object thisLock =new Object();
lock(thisLock)//参数必须基于引用类型对象
{
  //要运行的代码块
}

(2)使用monitor类实现线程同步

monitor类提供了通过向单个线程授予对象来控制对对象的访问,当一个线程拥有对象锁时,其它任何线程都不能获取该所。

Monitor.Enter(obj);//锁定代码块
{
        //所要执行的代码块
}
Monitor.Exit(obj);//解锁代码块

7、线程的中断和取消提前释放线程

(1) 中断线程    Interrupt()方法

在一个阻塞的线程上强行调用Interrupt()方法,将会抛出一个ThreadInterruptedException异常。中断一个线程只是将它从现在的等待中释放出来,并不会时线程结束。

(2)取消线程  Abort()方法

一个阻塞的线程可以通过Abort()方法而强行释放资源,将会抛出一个ThreadAbortException异常。

举例:

using System;
using System.Threading;
  
namespace AbortAndInterruptExp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("------------Interrupt方法执行情况---------------");
            Thread t1 = new Thread(DoWork);
            t1.Start();
            Thread.Sleep(1000);
            t1.Interrupt();
  
            t1.Join();
  
            Console.WriteLine("------------Abort方法执行情况---------------");
            Thread t2 = new Thread(DoWork);
            t2.Start();
            Thread.Sleep(1000);
            t2.Abort();
        }
  
        static void DoWork()
        {
            for (int i = 0; i < 10; i++)
            {
                try
                {
                    Console.WriteLine("第" + i + "循环。");
                    Thread.Sleep(500);
                }
                catch (ThreadInterruptedException e)
                {
                    Console.WriteLine("第" + i + "循环中,线程被中断,下次循环线程将继续运行。");
                }
                catch (ThreadAbortException e)
                {
                    Console.WriteLine("第" + i + "循环中,线程被终止,线程将不再继续运行");
                }
            }
        }
    }
}

 \

参考: https://www.2cto.com/kf/201505/399380.html

Interrupt()方法与Abort()方法的最大不同在于,当一个线程被调用它们时,如果线程当时不处于阻塞状态,那么Interrupt()会等到下一次阻塞发生时再执行操作,而Abort()方法则在线程执行到的地方抛出一个异常。在没有阻塞的线程中调用Abort()方法将会引发很严重的后果。

8、线程状态判断

            if (SaveToFile.ThreadState == ThreadState.Running)//判断线程SaveToFile是否处于运行状态
                    {

                     }                    
      

三、线程参数传递

上面中创建的线程都不带参数,下面讨论如何传递参数。

参考:C# 多线程参数传递

1、通过实体类传递

 //需要执行的线程
 public class FunctionClass  
    {  
        public static string TestFunction(string name, int age)  
        {   
            return name + " 的年龄是:" + age;  
        }  
    }  

//新建实体类
public class TransitionalClass  
    {  
        private string name = string.Empty;  
        private int age;  
        public string acceptResults = string.Empty;  
        public TransitionalClass(string name, int age)  
        {  
            this.name = name;  
            this.age = age;  
        }  
  
        public void TestFunction()  
        {  
            acceptResults = FunctionClass.TestFunction(this.name, this.age);  
        }  
    }

//执行线程
 //实例化ThreadWithState类,为线程提供参数    
          TransitionalClass tc = new TransitionalClass(" Jack", 42);  
          // 创建执行任务的线程,并执行    
          Thread t = new Thread(new ThreadStart(tc.TestFunction));  
          t.Start();  
          //获取返回值,通过 tc.acceptResults;    

四、线程安全

   在多线程编程时。一些敏感数据被多个线程同时访问,此时就使用同步访问技术,保证数据的完整性。

1、Lock

    lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。

    private static object  ojb = new object()
    lock(obj)
        {
                 //锁定运行的代码段
        } 

2、Lock对象的选取

        在共享线程中任何一个可见的对象只要它是应用类型,那么都可以用来作为线程同步的对象。 用对象本身或者此对象的类型作为同步化的对象时是不被推荐的。

3、死锁

        当有很多代码被写在锁语句中时,则会发生无数的并发操作,也就会使得其他的线程进入阻塞状态。死锁现象就是当两个线程相互等待另一个线程所占用的锁时,这两个线程都无法继续运行下去。

线程 1锁定资源 1尝试获取对资源 2的锁定。 同时,线程 2对资源 2有一个锁,它尝试获取对资源 1的锁。 两个线程永远不会放弃锁,因此发生死锁。

避免死锁的最简单方法是使用超时值。 Monitor类( system.threading.monitor ) 可以在获取锁期间设置超时。

if(Monitor.TryEnter(this, 500))
{
//critical section
}
catch (Exception ex)
{
}
finally
{
 Monitor.Exit();
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值