线程与进程

目录

什么是进程:

C#如何操作进程:

什么是线程:

解决的问题:

单线程的问题:

线程10个应用(创建,结束,终止,控制,跨线程访问,并发,线程池)

多线程的应用场景:


什么是进程:

是windows系统中的一个基本概念,他包含着一个运行程序所需要的资源。进程之间是相对独立的,一个进程无法直接访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行。windows系统是利用进程把工作划分为多个独立的区域,进程也可以理解为一个程序的基本边界。

如何操作进程:

//显示出本机所有线程的名称
Process[] ps=Process.GetProcesses();
foreach(Process p in ps)
{
    console.writeLine(p.processName);
}
    cosole.readkey();
//执行一个记事本进程
Process.Start("notepad.exe");
console.readkey();

什么是线程:

  1. 是windows任务调度的最小单位。
  2. 线程是程序中的一个执行流
  3. 所有的代码都必须执行在线程,有线程才能有代码执行

解决的问题:

进程是一个资源的拥有者,因而在进程的创建,撤销,和切换的过程中,系统必须为之付出较大的时空开销,限制了并发程度的进一步提高。

 

单线程的问题:

你的程序在做运算,如果用户想要拖动你程序的窗体,如果只有单线程的话,程序是没有办法同时做两件事情的。

解决方案:

在创建一个线程,就可以解决以上的问题,主线程负责拖动,子线程负责运算

private void BtnCount_Click(object serder,EventArgs e)
{   
   Thread myThread=new Thread(StartCount);  //参数内部的实质是委托
    myThread.Start();                       //start是标记可运行状态,但不是真正的执行,真正执行是操作系统说了算

}    

private void StartCount()
{
    int a=0;
    for(int i=0;i<1000000;i++)
    {
        a=i;
    }
    MessageBox.show(a.ToString());
}

 

线程10个应用(创建,结束,终止,控制,跨线程访问,并发,线程池)

1.那什么时候子线程开始执行?

Start()是标记可运行状态,但不是真正的执行,真正执行是操作系统说了算

2.那什么时候子线程什么时候结束?

在子线程中调用的那个方法运行结束子线程就结束了

3.那我们可以不等到子线程调用的那个方法运行结束就结束子线程么?

可以,但是非常暴力,容易抛异常,因为代码正在执行,就把它结束了

4.子线程和主线程他们真正的运行时间怎么控制?

用到Join()这个方法,让主线程等子线程执行完毕之后,在继续执行之后的代码。

例子:首先开启线程A,紧接着线程A调用了join()方法进入阻塞状态,那么线程必须等待线程A执行结束之后再往下执行,线程A执行完毕,线程B开启,进入睡眠,主线程执行,线程B睡眠结束,执行;

Thread myThread=new Thread(StartCount);  //参数内部的实质是委托
    myThread.Start();
    myThread.Join(1000);   //这个方法就是让主线程等这个子线程执行1秒,在这一秒内不管这个子线程执行完毕与否,都继续走主线程之后的代码

5.会不会出现父线程关闭了,子线程还在运行?

会,比如上面拖动窗体和计算的那个例子,如果你运算的时间过长,在你运算过程中,用户把你窗体关了,但是计算那个线程还在,最终还是会在你窗体在显示运算结果。如何避免呢?我们就运用到了后台线程,就可以避免这一问题,主窗体一关,其他线程全部关闭。

Thread myThread=new Thread(StartCount);  
myThread.IsBackground=true;  //设置为后台线程
myThread.Start();

6.之前线程执行都是不带参数的方法,那么线程可以执行带参数的方法么?

当然可以,看下图:

线程与进程_第1张图片

下面是该方法的参数列表

public delegate void ParameterizedThreadStart(object obj);

7.我们如何实现跨线程访问

首先我们现要知道什么是跨线程访问,下面代码中this.textBox1.Text=a.Tostring(); 就是跨线程访问。

private void BtnCount_Click(object serder,EventArgs e)
{   
   Thread myThread=new Thread(StartCount);  //参数内部的实质是委托
    myThread.Start();                       //start是标记可运行状态,但不是真正的执行,真正执行是操作系统说了算

}    

private void StartCount()
{
    int a=0;
    for(int i=0;i<1000000;i++)
    {
        a=i;
    }
    this.textBox1.Text=a.Tostring();   //跨线程访问,textbox框是由主线程创建的
}

1).最直接的,关闭跨线程检测,但是非常不好

线程与进程_第2张图片

2).Invoke方法(委托,去找创建textbox的线程,由创建textbox的线程来执行showtextboxvalue方法,)

private void BtnCount_Click(object serder,EventArgs e)
{   
   Thread myThread=new Thread(StartCount);  //参数内部的实质是委托
    myThread.Start();                       //start是标记可运行状态,但不是真正的执行,真正执行是操作系统说了算

}    

private void StartCount()
{
    int a=0;
    for(int i=0;i<1000000;i++)
    {
        a=i;
    }
    if(this.textBox1.InvokeRequired)//是否要对文本框进行跨线程访问
    {
//<>泛型约束,约束一下调用的方法要有TextBox和string类型的参数
        this.textBox1.Invoke(new Action(showTextBoxValue),this.textBox1,a.Tostring());
    }
    this.textBox1.Text=a.Tostring();
}

Private void ShowTextBoxValue(TextBox txt,string value)
{
}

8.如果两个线程同时用一个方法怎么办?

加锁

一个请求对应一个线程,页面一刷新就发一次请求,如果用户狂刷,狂发请求,怎么办?---线程池

9.为什么要有线程池?

  • 不停初始化线程的内存消耗,任何时候资源都是有限的,无限制的新建线程会占用大量的内存空间。
  • 在CPU资源有限的情况下,新建更多的线程不仅不能达到并发处理客户端消息的目的,相反由于线程间的切换更加频繁,会导致处理时间更长,效率更加低下。
  • 线程本身的创建与销毁都需要耗费服务器资源。
  • 不方便对线程进行集中管理。

线程池:提高了线程的利用率,非常适合工作任务非常小,而且又需要使用单独的线程来解决的问题。

10.什么时候用线程池,什么时候用手动创建线程?

1.我们向手动关闭线程的话那么必须手动创建

2.我们需要对线程池的线程的优先级做设置的情景下,只能使用手动创建线程(线程池里面取出来的都是normal,都是后台线程)

3.如果执行的线程执行时间特别长,建议手动创建线程

 

 

多线程的应用场景:

1.比如360要杀毒,但是你还要拖动你的窗体或者其他的操作

2.购物--生成订单(算订单,发邮件等等)到支付中间有很多工作,就可以用线程来处理其中的工作

3.希望获得更多操作系统资源尽快处理我们的业务,缩短处理时间

4.如果是一个非常复杂的操作。需要占用非常长的时间,而窗体又不允许阻塞UI线程

 

 

 

你可能感兴趣的:(ASP)