目录
- 前言
- 一、单线程
- 二、多线程-Thread
- 多线程是都多少个的时候会导致性能变差
- 三、多线程-Task类
- Task的优势
- 四、异步- await
- await
- 注意:多个Task Run()天剑await后,变成了同步执行
- 解决方法
- 更新时间
前言
参考视频:C#基础教程 多线程编程入门 Thread/Task/async/await 简单秒懂!
中型项目中就会涉及到性能的问题。我主要是在C# winform中创建多个需要持续监听的事件后,会遇到性能的问题。这里面一般会遇到选择是多线程的方式还是异步的方式,有时候定时器创建多个后,也会导致性能变差。
一、单线程
单线程:就是一次只能做一件事。
点击炒菜后,只能等菜炒好了,才能做其他事【如下图:】
private void button1_Click(object sender, EventArgs e)
{
Thread.Sleep(3000);
MessageBox.Show("一盘菜炒好了【青椒土豆丝】","友情提示");
Thread.Sleep(5000);
MessageBox.Show("一盘菜炒好了【红烧肉】", "友情提示");
}
二、多线程-Thread
多线程:几乎同时完成多件事。
例如,一边炒菜,一边做饭。
上面就是创建个线程类并实例化,最后通过Start()方法来启动。
但是,启动做什么事情呢?这里就需要在实例化的过程中告诉线程。下面是采用lamda方法 () => { }
即、new 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#中较常用的方法,是任务类,下图就是任务开始执行的写法:
但是,任务执行什么操作,是要在Run()中指示清楚的。如下代码:
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("菜做好了,开始吃饭");
});
}