C# 多线程(学习笔记13)
1.进程与线程
进程是资源管理的最小单位,有自己的内存空间,一个进程可以有多个线程,各线程之间共享进程的系统资源。
多线程的意义在于多任务的并发执行。多线程对于自动化领域意义重大,例如一个线程去访问硬件设备读写数据,另一个线程需要操作数据库,
如果放在同一个线程中,那么就会造成程序的严重卡顿。
2.简单示例
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinFormC10
{
public partial class Form1 : Form
{
private delegate void FlushClient();//代理
int num = 0;
public Form1()
{
InitializeComponent();
// 禁止跨线程检查
// Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(M)
{
IsBackground = true
};
thread.Start();
}
private void M()
{
while (true)
{
S();
Thread.Sleep(1000);
}
}
private void S()
{
if (this.InvokeRequired)//等待异步
{
num++;
FlushClient fc = new FlushClient(S);
this.Invoke(fc);//通过代理调用刷新方法
}
else
{
this.Text = num.ToString();
}
}
}
}
3. Thread类
3.1 属性
| 序号 | 属性 | 作用 |
|---|---|---|
| 1 | IsBackground | 是否是后台线程。后台线程会在前台线程结束后自动终止。 |
| 2 | IsAlive | 线程是否活动,false表示终止。 |
| 3 | Priority | 线程优先级 |
| 4 | ThreadState | 获得当前的线程状态 |
| 5 | Name | 线程名称 |
| 6 | ManagedThreadId | 当前线程ID |
3.2 方法
| 序号 | 方法 | 作用 |
|---|---|---|
| 1 | Sleep | 休眠,线程挂起 |
| 2 | Abort | 终止(释放)。 |
| 3 | Start | 启动 |
Thread类属于比较旧版本的线程类,一般在.Net Frmaework3.5以下版本使用。
4. ThreadPool
每个进程只有一个线程池,线程池的线程都是后台线程。
- 有点
作为后台线程运行;
线程执行时间较短;
默认优先级运行,无需设置优先级。
线程状态无须监控;
using System;
using System.Threading;
namespace ThreadPoolTest;
public class Program
{
public static int count = 1000;
public static void DoWork(object s)
{
for (int i = 0; i < count; i++)
{
Console.Write(s);
}
}
public static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(DoWork, "+");
ThreadPool.QueueUserWorkItem(DoWork, "=");
for (int i = 0; i < count; i++)
{
Console.Write("-");
}
Thread.Sleep(100000);
}
}
获得最小线程数:ThreadPool.GetMinThreads
获得最大线程数:ThreadPool.GetMaxThreads
- 缺点
不知道线程状态( 不支持线程的取消,完成、失败通知等)。
不支持线程执行的先后顺序。
对长时间执行的线程没有后台优化。
5. Task
基于任务的异步编程模型,性能和易用性得到进一步提升。
由ThreadPool来执行和回收。
Task执行完成后,不能再回到创建处。
5.1 基本用法
using System;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
namespace TaskTest01
{
class Program
{
private const int CNT = 1000000;
private volatile static bool flag = false;
static void Main(string[] args)
{
Task task01 = Task.Run(() =>
{
for (int i = 0; i < CNT; i++)
{
if (flag)
{
Console.Write("\r\n");
break;
}
Console.Write("...");
Thread.Sleep(50);
}
});
while (true)
{
// 查询 task1的状态
if (task01.IsCompleted)
{
Console.WriteLine("Task task01 is Completed!");
break;
}
// 输入q会退出
var q = Console.ReadKey().KeyChar;
if (q == 'q')
{
flag = true;
}
}
Console.ReadKey();
}
private static void n()
{
for (int i = 0; i < CNT; i++)
{
Console.Write("-");
}
}
}
}
5.2 耗时任务分配专用线程
using System;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
namespace TaskTest01
{
class Program2
{
private const int CNT = 1000000;
private volatile static bool flag = false;
static void Main(string[] args)
{
// 分配专用线程处理
Task task01 = new Task(n, TaskCreationOptions.LongRunning);
task01.Start();
while (true)
{
if (task01.IsCompleted)
{
Console.WriteLine("Task task01 is Completed!");
break;
}
// 输入q会退出
var q = Console.ReadKey().KeyChar;
if (q == 'q')
{
flag = true;
}
}
Console.ReadKey();
}
private static void n()
{
for (int i = 0; i < CNT; i++)
{
if (flag)
{
Console.Write("\r\n");
break;
}
Console.Write("...");
Thread.Sleep(50);
}
}
}
}
6. async/await
async/await在C#5.0引入,使得异步编程更加容易。
一般用于耗时较长的操作。
async/await 是对task的进一步封装。
async和await 一般是成对出现的。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinFormC10
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private async void Button1_Click(object sender, EventArgs e)
{
// 等待Calc的结果
string s = await Calc();
textBox1.Text = s;
textBox1.BackColor = Color.Red;
}
/// <summary>
/// 异步执行Calc
/// </summary>
/// <returns></returns>
private Task<string> Calc()
{
string tid = Thread.CurrentThread.ManagedThreadId.ToString();
string s = "";
return Task.Run(() =>
{
for (int i = 1; i <= 9999999; i++)
{
s = i.ToString();
}
return tid + " " + s;
});
}
}
}
本文来自博客园,作者:huiy_小溪,转载请注明原文链接:https://www.cnblogs.com/huiy/p/19267135

浙公网安备 33010602011771号