操作系统由多个进程的运行来维持的,进程又被细化为线程(Thread)。一个完整的进程拥有独立的内存空间,同一个进程内的线程是共享内存空间和数据。
在C#中线程使用委托的方式来完成,定义线程的同时,必须定义对应的委托对象,最后还要定义一个能够被线程调用的方法。
简单多线程
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp4
{
public partial class Form1 : Form
{
// 定义委托
delegate void SetText(string s);
// 定义委托
SetText setText;
// 定义委托
Thread thread1;
public Form1()
{
InitializeComponent();
label1.Text = "0";
// 实例化委托
setText = new SetText(set_lableText);
}
private void button1_Click(object sender, EventArgs e)
{
// 实例化线程,调用run方法
thread1 = new Thread(new ThreadStart(run));
// 开始线程
thread1.Start();
}
private void set_lableText(string s)
{
label1.Text = s;
}
private void run()
{
for (int i = 0; i < 10; i++)
{
// 通过调用委托,改变标签的值
label1.Invoke(setText, new object[] { i.ToString() });
// 线程休眠1000毫秒
Thread.Sleep(1000);
}
}
private void Form1_Formclosing(object sender, FormClosedEventArgs e)
{
if (thread1.IsAlive) // 判断现场是否存在
{
// 注销thread1
thread1.Abort();
}
}
}
}
线程的生命周期
线程同步
当遇到以下下两种情况,需要线程间同步执行:
1、多个线程向一个变量复制或多线程改变同一对象属性
2、某些线程等待另一些线程执行某些操作后才能执行。
可以使用lock加锁和Monitor类实现线程同步。
以下两种实现方法等效:
lock(x)
{
DoSomthing();
}
object myobj = (object)x;
System.Threading.Monitor.Enter(myobj);
try
{
DoSomthing();
}
finally
{
System.Threading.Monitor.Exit(myobj);
}
具体实例
using System;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
private static object myObj = new object();
[STAThread]
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(Do));
thread1.Name = " 线程1 ";
Thread thread2 = new Thread(new ThreadStart(Do));
thread2.Name = " 线程2 ";
thread1.Start();
thread2.Start();
// Join方法主要是用来阻塞调用线程,直到某个线程终止或经过了指定时间为止。
thread1.Join();
thread2.Join();
Console.ReadKey();
}
static void Do()
{
if (!Monitor.TryEnter(myObj))
{
Console.WriteLine(" 不能访问" + Thread.CurrentThread.Name);
return;
}
try
{
Monitor.Enter(myObj);
Console.WriteLine(" 可以访问" + Thread.CurrentThread.Name);
// 线程休眠
Thread.Sleep(5000);
}
finally
{
Monitor.Exit(myObj);
}
}
}
}
当线程1获取了myOjb对象独占时,线程2尝试调用TryEnter,此时会由于午发获取独占权而返回false。
参考
https://learn.microsoft.com/zh-cn/dotnet/standard/threading/using-threads-and-threading