您的当前位置:首页正文

记录|多线程和异步简单理解

2024-11-08 来源:个人技术集锦


前言

中型项目中就会涉及到性能的问题。我主要是在C# winform中创建多个需要持续监听的事件后,会遇到性能的问题。这里面一般会遇到选择是多线程的方式还是异步的方式,有时候定时器创建多个后,也会导致性能变差。


一、单线程

单线程:就是一次只能做一件事。
点击炒菜后,只能等菜炒好了,才能做其他事【如下图:】

        private void button1_Click(object sender, EventArgs e)
        {
            Thread.Sleep(3000);
            MessageBox.Show("一盘菜炒好了【青椒土豆丝】","友情提示");
            Thread.Sleep(5000);
            MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
        }

二、多线程-Thread

多线程:几乎同时完成多件事。
例如,一边炒菜,一边做饭。

        private void button2_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(() => {
                Thread.Sleep(3000);
                MessageBox.Show("一盘菜炒好了【青椒土豆丝】", "友情提示");
                Thread.Sleep(5000);
                MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
            });
            t.Start();
        }

多线程是都多少个的时候会导致性能变差


三、多线程-Task类

C#中较常用的方法,是任务类,下图就是任务开始执行的写法:

        private void button3_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                Thread.Sleep(3000);
                MessageBox.Show("一盘菜炒好了【青椒土豆丝】", "友情提示");
                Thread.Sleep(5000);
                MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
            });
        }

Task的优势

上面用一个Task,是需要花8秒做完青椒土豆丝和红烧肉。
可以用2个Task,让两盘菜同时做,只需要5秒钟。

        private void button4_Click(object sender, EventArgs e)
        {
            Task.Run(() => {
                Thread.Sleep(3000);
                MessageBox.Show("一盘菜炒好了【青椒土豆丝】", "友情提示");
            });
            Task.Run(() => {
                Thread.Sleep(5000);
                MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
            });
        }

四、异步- await

我们想两盘菜做好后再开始吃饭。下面的写法是否有问题呢:

        private void button5_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                Thread.Sleep(3000);
                MessageBox.Show("一盘菜炒好了【青椒土豆丝】", "友情提示");
                Thread.Sleep(5000);
                MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
            });
            MessageBox.Show("菜做好了,开始吃饭");
        }

await

在Task前面添加await,让任务变为异步。此时方法名签名需要添加async。如下代码所示:

        private async void button5_Click(object sender, EventArgs e)
        {
           await Task.Run(() =>
            {
                Thread.Sleep(3000);
                MessageBox.Show("一盘菜炒好了【青椒土豆丝】", "友情提示");
                Thread.Sleep(5000);
                MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
            });
            MessageBox.Show("菜做好了,开始吃饭");
        }

这样子,就实现了等炒菜这件事情完成后,再通知。

注意:多个Task Run()天剑await后,变成了同步执行

        private async void button5_Click(object sender, EventArgs e)
        {
            await Task.Run(() => {
                Thread.Sleep(3000);
                MessageBox.Show("一盘菜炒好了【青椒土豆丝】", "友情提示");
            });
            await Task.Run(() => {
                Thread.Sleep(5000);
                MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
            });
            MessageBox.Show("菜做好了,开始吃饭");
        }

解决方法

创建Task类型的List类,然后将B需要开始执行的前置条件A都放入到列表中。
之后,等列表中的所有内容都完成后,开始执行B。

        private void button5_Click(object sender, EventArgs e)
        {
            List<Task> ts = new List<Task>();
            ts.Add(
                            Task.Run(() =>
                            {
                                Thread.Sleep(3000);
                                MessageBox.Show("一盘菜炒好了【青椒土豆丝】", "友情提示");
                            })
                );
            ts.Add(
                            Task.Run(() =>
                            {
                                Thread.Sleep(5000);
                                MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
                            })
                );

            Task.WhenAll(ts).ContinueWith(t =>
            {
                MessageBox.Show("菜做好了,开始吃饭");
            });
        }


更新时间

Top