14、让线程等待一段时间
让线程等待一段时间
知识点概述
在多线程编程中,经常需要让线程暂停执行一段时间。.NET提供了多种方式来实现线程等待:
- Thread.Sleep(): 使当前线程暂停指定的时间
- Task.Delay(): 异步等待指定时间(推荐用于异步方法)
- Thread.Yield(): 让出CPU时间片给其他线程
- SpinWait: 忙等待,适用于短时间等待
- ManualResetEvent/AutoResetEvent: 基于事件的等待机制
代码案例
案例1:Thread.Sleep基本用法
using System;
using System.Threading;
using System.Diagnostics;
class ThreadSleepDemo
{
static void Main()
{
Stopwatch sw = Stopwatch.StartNew();
Console.WriteLine($"开始时间: {DateTime.Now:HH:mm:ss.fff}");
// 让主线程休眠2秒
Thread.Sleep(2000);
Console.WriteLine($"结束时间: {DateTime.Now:HH:mm:ss.fff}");
Console.WriteLine($"实际耗时: {sw.ElapsedMilliseconds}ms");
}
}
案例2:多线程中的Sleep应用
using System;
using System.Threading;
class MultiThreadSleepDemo
{
static void Main()
{
// 创建多个线程,每个线程有不同的休眠时间
for (int i = 1; i <= 3; i++)
{
int threadNum = i;
Thread thread = new Thread(() => WorkWithSleep(threadNum));
thread.Name = $"Thread-{threadNum}";
thread.Start();
}
Console.WriteLine("主线程继续执行其他任务...");
Thread.Sleep(5000); // 主线程等待5秒观察其他线程
Console.WriteLine("主线程结束");
}
static void WorkWithSleep(int threadNum)
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"{Thread.CurrentThread.Name}: 执行步骤 {i + 1} - {DateTime.Now:HH:mm:ss.fff}");
// 不同线程有不同的休眠时间
Thread.Sleep(threadNum * 500);
}
Console.WriteLine($"{Thread.CurrentThread.Name}: 完成所有任务");
}
}
案例3:Task.Delay异步等待
using System;
using System.Threading.Tasks;
using System.Diagnostics;
class TaskDelayDemo
{
static async Task Main()
{
Console.WriteLine("开始异步等待演示");
// 启动多个异步任务
Task task1 = DelayedTaskAsync("任务1", 1000);
Task task2 = DelayedTaskAsync("任务2", 2000);
Task task3 = DelayedTaskAsync("任务3", 1500);
Console.WriteLine("所有任务已启动,主线程继续执行...");
// 等待所有任务完成
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("所有异步任务完成");
}
static async Task DelayedTaskAsync(string taskName, int delayMs)
{
Console.WriteLine($"{taskName} 开始 - {DateTime.Now:HH:mm:ss.fff}");
await Task.Delay(delayMs); // 异步等待
Console.WriteLine($"{taskName} 完成 - {DateTime.Now:HH:mm:ss.fff}");
}
}
案例4:Thread.Yield和SpinWait的使用
using System;
using System.Threading;
using System.Diagnostics;
class YieldAndSpinWaitDemo
{
private static bool _flag = false;
static void Main()
{
Console.WriteLine("Thread.Yield 演示:");
YieldExample();
Console.WriteLine("\nSpinWait 演示:");
SpinWaitExample();
}
static void YieldExample()
{
Thread producer = new Thread(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"生产者: 生产项目 {i + 1}");
Thread.Yield(); // 让出CPU时间片
}
});
Thread consumer = new Thread(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"消费者: 消费项目 {i + 1}");
Thread.Yield(); // 让出CPU时间片
}
});
producer.Start();
consumer.Start();
producer.Join();
consumer.Join();
}
static void SpinWaitExample()
{
_flag = false;
// 启动设置标志的线程
Thread setter = new Thread(() =>
{
Thread.Sleep(1000); // 模拟一些工作
_flag = true;
Console.WriteLine("标志已设置为 true");
});
// 启动等待标志的线程
Thread waiter = new Thread(() =>
{
SpinWait spinWait = new SpinWait();
while (!_flag)
{
spinWait.SpinOnce(); // 忙等待
}
Console.WriteLine("检测到标志变化,继续执行");
});
waiter.Start();
setter.Start();
waiter.Join();
setter.Join();
}
}
案例5:可中断的等待
using System;
using System.Threading;
class InterruptibleWaitDemo
{
static void Main()
{
Thread workerThread = new Thread(InterruptibleWork);
workerThread.Start();
Console.WriteLine("按任意键中断线程等待...");
Console.ReadKey();
// 中断线程的等待
workerThread.Interrupt();
workerThread.Join();
Console.WriteLine("程序结束");
}
static void InterruptibleWork()
{
try
{
Console.WriteLine("开始长时间等待...");
Thread.Sleep(10000); // 等待10秒
Console.WriteLine("等待完成");
}
catch (ThreadInterruptedException)
{
Console.WriteLine("等待被中断");
}
}
}
知识点总结
- Thread.Sleep(): 阻塞当前线程指定时间,适用于同步场景
- Task.Delay(): 异步等待,不阻塞线程,适用于异步方法
- Thread.Yield(): 主动让出CPU时间片,给其他线程执行机会
- SpinWait: 忙等待机制,适用于短时间等待,避免线程切换开销
- 可中断等待: 使用ThreadInterruptedException处理等待中断
- 性能考虑: 选择合适的等待方式对应用性能影响很大
- 最佳实践: 在异步环境中优先使用Task.Delay,在同步环境中使用Thread.Sleep

浙公网安备 33010602011771号