摘要
在C#中,线程的生命周期是由多个状态组成的,这些状态包括线程的创建、启动、挂起、等待、恢复和终止。
正文
1. 创建线程
线程的生命周期从创建开始。在C#中,可以通过System.Threading.Thread
类的实例化来创建一个线程。创建线程时,需要指定一个将在该线程上执行的方法。
Thread myThread = new Thread(new ThreadStart(MyMethod));
这里,MyMethod是一个无参方法,它定义了线程的执行内容。
2. 启动线程
创建线程后,它处于就绪状态,等待CPU的调度。通过调用Thread
对象的Start
方法来启动线程,使其进入可运行状态。
一旦线程开始执行,它会自动地调用其对应的方法。
3. 挂起线程
线程可以被显式地挂起,即暂时停止执行,这通常是通过调用Suspend
方法实现的。不过,需要注意的是,Suspend
方法在.NET Framework 2.0之后已被弃用,因为它可能导致死锁。现在建议使用其他同步技术,如ManualResetEvent
或Monitor
等。
4. 线程等待
线程在执行过程中,可能会因为某些条件未满足而进入等待状态。例如,当线程调用Join
方法等待另一个线程完成时,或者使用Thread.Sleep
暂停当前线程的执行。
myThread.Join(); // 等待myThread线程完成
Thread.Sleep(1000); // 当前线程暂停1秒
5. 恢复线程
对于被挂起的线程,可以通过调用Resume
方法来恢复其执行。同样地,Resume
方法也已被弃用,建议使用其他同步机制来控制线程的执行。
6. 终止线程
线程的执行可以通过多种方式结束:
线程一旦终止,它的状态变为Stopped,此时它的生命周期结束。
因为我们是用Winform做线程实例,所以需要跨线程UI操作的一些技术。
示例
一个例子,点击开始,会在文本框中每10毫秒输出一个点。
创建线程
通过new 一个Thread对象并指定线程执行函数创建线程。调用Start方法开启线程
private void btnStart_Click(object sender, EventArgs e)
{
Thread thread = new Thread(ShowDot);
thread.Start();
}
void ShowDot()
{
for (int i = 0; i < 100; i++)
{
this.Invoke((() =>
{
txtValue.Text += ".";
}));
System.Threading.Thread.Sleep(10);
}
}
通过在线程函数中调用Thread.Sleep()
暂停当前线程,使线程进入休眠状态。此时线程会占用尽可能少的CPU时间。
线程等待
假设有线程t,在主程序中调用了t.Join()方法,该方法允许我们等待直到线程t完成。当线程t完成 时,主程序会继续运行。借助该技术可以实现在两个线程间同步执行步骤。第一个线程会等待另一个线程完成后再继续执行。第一个线程等待时是处于阻塞状态(正如暂停线程中调用 Thread.Sleep方法一样)
private void btnStart_Click(object sender, EventArgs e)
{
Thread thread = new Thread(ShowDot);
thread.Start();
thread.Join();
Thread thread1 = new Thread(ShowDot1);
thread1.Start();
}
void ShowDot()
{
for (int i = 0; i < 100; i++)
{
this.BeginInvoke((() =>
{
txtValue.Text += ".";
}));
System.Threading.Thread.Sleep(10);
}
}
void ShowDot1()
{
for (int i = 0; i < 100; i++)
{
this.BeginInvoke((() =>
{
txtValue1.Text += ".";
}));
System.Threading.Thread.Sleep(10);
}
}
终止线程
private void btnStart_Click(object sender, EventArgs e)
{
Thread thread = new Thread(ShowDot);
thread.Start();
// SpinWait 不仅仅只是空循环。谨慎实现后,它可以提供适用于一般情况的正确旋转行为,
// 并且本身能够在旋转时间够长(大致是内核转换所需的时间长度)时自行启动上下文切换。
//有点像Sleep
SpinWait.SpinUntil(() => false, 100);
thread.Interrupt();
}
void ShowDot()
{
for (int i = 0; i < 100; i++)
{
this.BeginInvoke((() =>
{
txtValue.Text += ".";
}));
System.Threading.Thread.Sleep(10);
}
}
thread.Abort(); 这个在.Net中不支持了,只在.Net Framework中支持。
注意
在多线程编程中,正确管理线程的生命周期是非常重要的。不当的线程管理可能会导致资源泄露、死锁或其他并发问题。因此,建议使用高级的并发和同步机制,如任务并行库(TPL)中的Task
类,它提供了更加丰富和灵活的控制方式。
该文章在 2024/3/31 1:13:49 编辑过