CSharp学习

一、C#多线程

关键字集

  • Task:线程关键字

  • async:与await成对使用

  • await:异步线程,与async成对使用:等待线程结束后再执行UI

线程方法

  • Task.WaitAll(task1, task2):等待两个任务都完成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 定义两个任务
Task task1 = Task.Run(() =>
{
// 模拟一个长时间运行的任务
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Task 1: Working {i + 1}/5");
Task.Delay(1000).Wait(); // 延迟1秒
}
Console.WriteLine("Task 1: Completed");
});

Task task2 = Task.Run(() =>
{
// 模拟另一个长时间运行的任务
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Task 2: Working {i + 1}/5");
Task.Delay(1500).Wait(); // 延迟1.5秒
}
Console.WriteLine("Task 2: Completed");
});

// 等待两个任务都完成
Task.WaitAll(task1, task2);
  • Task.WhenAll(线程集合):线程集合全部执行完后
1
2
3
4
private async void 方法()
{
await Task.Run(异步线程);
}

并发线程:同样成对使用async和await

1
2
3
4
5
6
7
8
//创建线程集合
List<Task<string>> Tanks = new();

//将需要运行的方法都Add进Task中运行
Data.books.Foreach(book => Tasks.Add(Task.Run(book.Search)));

//自定义的字符串返回值,线程集合全部执行完后返回字符串集合
var tasks = await Task.WhenAll(Tasks);
  • Task.ContinueWith():Task线程回调方法,防止先结束的线程等待(未用到await,故不需async)
    • 问题:主线程不会等待,继续往下执行
    • 解决:事件(event)
1
2
3
4
5
//循环创建打开线程,线程完成方法,循环只负责打开
foreach (var book in Date.Books)
{
Task.Run(book.Search).ContinueWith(t => AppendLine("输出"));
}

所有逻辑结束之后执行事件

一、单线程

单线程阻塞窗口运行

1
2
3
4
5
6
7
private void button1_Click(object sender, EventArgs e)
{
Thread.Sleep(3000);
MessageBox.Show("素菜做好了","友情提示");
Thread.Sleep(5000);
MessageBox.Show("荤菜做好了", "友情提示");
}

二、Thread线程

新开一个线程用来执行方法委托,也可使用Lambda表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
//Thread
private void button2_Click(object sender, EventArgs e)
{
//开启一个新的线程,Thread括号内是委托方法
Thread t = new Thread(() => //使用Lambda表达式
{
Thread.Sleep(3000);
MessageBox.Show("素菜做好了", "友情提示");
Thread.Sleep(5000);
MessageBox.Show("荤菜做好了", "友情提示");
});
t.Start();
}

三、Task任务(C#更推荐)

Task底层使用的也是Thread线程,Run一个方法委托或者Lambda表达式

Task:提供了很多线程相关的管理如线程池,性能会更好,管理更方便

1
2
3
4
5
6
7
8
9
10
11
//Task任务
private void button3_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
Thread.Sleep(3000);
MessageBox.Show("素菜做好了", "友情提示");
Thread.Sleep(5000);
MessageBox.Show("荤菜做好了", "友情提示");
});
}

四、两个Task同时执行

将每一种菜放入不同线程,同时执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//两个Task同时执行
private void button4_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
Thread.Sleep(3000);
MessageBox.Show("素菜做好了", "友情提示");
});
Task.Run(() =>
{
Thread.Sleep(5000);
MessageBox.Show("荤菜做好了", "友情提示");
});
}

五、异步线程

!!不使用异步线程则会先执行MessageBox.Show(“饭做好了,快来吃吧”);!!

加入async和await关键字使线程变成异步线程

异步线程:Task执行完才执行Run外的程序(等某个线程完成以后才去做另外一件事情)

1
2
3
4
5
6
7
8
9
10
11
12
13
//开饭
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同时执行,则线程之间就不是并行的了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//开饭
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("饭做好了,快来吃吧");
}