专题:多线程

基础篇就算更完了……

后面整理下,出点专题的东西

什么是进程,线程

简单的说每一个应用程序都是一个进程,而每一个进程,又是由多个线程组成的……

操作进程的类

Process

这个类中有一些方法

Process[] pro = Process.GetProcesses() 静态方法,得所有的进程

pro[3].Kill()关闭线程

Process.Start(“进程名字”) 这样可以打开某个程序

单线程会面临的问题

每当运行 一个自己写的程序的时候,会有一个主线程分配过来,我们在操作窗体的时候,主线程就在帮我们进行操作,而一旦我们窗体上有一些比较麻烦的事情在处理的时候,主线程就被占用了,这个时候窗体就会呈现出假死的状态。

解决

怎么解决这个问题呢?让主线程不被占用,开一个新的线程处理命令似乎就是一个比较不错的想法。

Thread th = new Thread(这里传入的是一个方法) 这样就开启了一个新的线程
试了一下,这个方法是不能有参数的……

th.Start() 可以理解为启动线程,但是实际上是告诉 CPU 这个线程准备完毕,并不会立即执行代码,我们的代码是不能直接控制 CPU 的,所以就会出现写了多线程也卡的情况,因为 CPU 何时执行还要看 CPU 的心情……

因为我们开新县城就是为了让他运行一个方法,所以实例化新的线程(或许说成开一个新的线程会比较恰当)的时候我们传入的参数是一个方法。

把一个方法作为参数传入另一个方法,这个就是委托。(后面有具体聊这个的)

写了多线程还有一个别的问题出现

当我们写了多线程之后,主窗口是不会假死了,但是主窗口关闭后,如果位于另一个线程的事情还没结束,那么他就会继续执行,直到完成,这就不是我们想要的样子了……
因为我们默认情况下开的线程都是前台线程,我们关闭主窗口只是表象,所有的前台线程并没有结束,于是程序并没有真的退出,想要解决这个问题可以把我们新开的这个线程变成后台线程。
只需要 th.IsBackground = true;
这样就会将这个线程设置为后台线程,只要主程序关闭,它就跟着强制结束了。
所以这段代码变成这样:

Thread th = new Thread(这里传入的是一个方法) ;
th.IsBackground = true;
th.Start();

问题这东西,解决一个还有一个

程序会默认检测是否存在跨线程访问,因为跨线程访问是不被允许的,不过既然是检测出来的……
我们可以把这个检测关掉……

Control.CheckForIllegalCrossThre……反正就是最长的那个,然后设置成 false
这个东西可以写在窗体加载的地方,大概的意思就是,我这个窗体里面的线程都是不用你去检查了……

不过,跨线程,往往会产生各种异常……
比较常见的就是窗体关闭,但是后台线程的东西还没完事,这样的话,主线程关了,主线程里面的东西就没了,由于种种原因,后台线程没有同步关闭,所以后台线程就找不到这个东西了,所以就抛出异常了……

解决办法也很简单,就是在窗体的 Closing 事件中写上一段关闭后台线程的代码。
先判断下这个后台线程是不是已经关了(关了 th == null 就成立了)

if(th !== null )判断线程是不是已经关了
{
th.Abort();没关的话就关上
}

写在 Closing 事件中就保证了一定是关闭线程这个代码吗执行完了之后,才关闭窗体,也就是关闭主线程,这样就不会出现上面说的异常了。

线程一旦被关闭,就不能再被打开了

使用多线程,就是为了能让计算机同时做一些事情,从而节约时间,也会一定程度避免主界面无响应的事情出现。

还有个好玩的
Thread.Sleep(毫秒)让主线程睡一段时间,然后再继续执行

乍一看,多线程似乎就是解决了个卡一点的问题,但事实上,有些场景真的非用不可……

比如摇奖这个东西,一旦摇奖开始,不停地生成随机数打印在窗体上,直到按下停止按钮,这个过程就很矛盾,因为主线程在忙着生成随机数和打印这两件事,所以主窗体就死掉了……那么按下停止按钮这个操作就没法实现了……
这个时候就需要开一个线程去生成随机数并打印,而主线程负责检测是不是按下了停止按键,来结束这个后台进程。

多线程其实还有一些莫名其妙的异常

不妨直接把他 try 掉……
嗯……线程有风险,如坑需谨慎……

文末案例

写一个小摇奖程序,嗯……摇起来就行了,奖不奖的不重要。
貌似。。最后的最后,我还是不爱写注释……

using System;
using System.Threading;
using System.Windows.Forms;

namespace _07_YaoAYao
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            label1.Text = "?";
            label2.Text = "?";
            label3.Text = "?";
            kaiGuan.Text = "开";
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        public void YaoJiang()
        {
            Random r = new Random();
            while (zhuan_ing)
            {
                label1.Text = ((int)r.Next(0, 10)).ToString();
                label2.Text = ((int)r.Next(0, 10)).ToString();
                label3.Text = ((int)r.Next(0, 10)).ToString();
            }
        }

        Thread th;
        bool zhuan_ing = false;
        
        private void kaiGuan_Click(object sender, EventArgs e)
        {
            if (zhuan_ing)
            {
                th.Abort();
                zhuan_ing = false;
                kaiGuan.Text = "开";
            }
            else
            {
                th = new Thread(YaoJiang);
                th.IsBackground = true;
                th.Start();
                zhuan_ing = true;
                kaiGuan.Text = "停";
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (th!=null)
            {
                th.Abort();
            }
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值