C#线程启动的几种实现方法小结

一、基础线程启动方式

1. Thread类直接启动

// 基本线程启动
Thread thread = new Thread(new ThreadStart(SimpleMethod));
thread.Start();

void SimpleMethod()
{
    Console.WriteLine($"线程ID:{Thread.CurrentThread.ManagedThreadId} 正在执行");
}
图片[1]_C#线程启动的几种实现方法小结_知途无界

2. 带参数的线程启动

// 使用ParameterizedThreadStart传递参数
Thread paramThread = new Thread(new ParameterizedThreadStart(ParamMethod));
paramThread.Start("参数数据");

void ParamMethod(object data)
{
    Console.WriteLine($"接收到参数: {data}");
}

3. Lambda表达式简化

// 使用lambda表达式简化线程创建
Thread lambdaThread = new Thread(() => 
{
    Console.WriteLine($"Lambda线程执行,ID:{Thread.CurrentThread.ManagedThreadId}");
});
lambdaThread.Start();

二、线程池技术

1. ThreadPool基础使用

// 使用线程池执行任务
ThreadPool.QueueUserWorkItem(state => 
{
    Console.WriteLine($"线程池任务执行,状态: {state}");
}, "自定义状态");

2. 带返回值的线程池任务

// 使用Task.Run(本质也是线程池)
Task<int> task = Task.Run(() => 
{
    Thread.Sleep(1000);
    return 42;
});
Console.WriteLine($"任务结果: {task.Result}");

三、Task并行库(Task Parallel Library)

1. 基本Task启动

// 创建并启动Task
Task task = new Task(() => 
{
    Console.WriteLine($"Task线程ID:{Thread.CurrentThread.ManagedThreadId}");
});
task.Start();

2. Task.Run快捷方式

// 使用Task.Run立即调度任务
Task.Run(() => 
{
    Console.WriteLine("使用Task.Run启动的任务");
});

3. 带返回值的Task

Task<string> returnTask = Task.Run(() => 
{
    return $"当前时间: {DateTime.Now}";
});
Console.WriteLine(returnTask.Result);

四、高级线程控制

1. 线程取消机制

// 使用CancellationToken取消线程
CancellationTokenSource cts = new CancellationTokenSource();
Task longRunningTask = Task.Run(() => 
{
    while (!cts.IsCancellationRequested)
    {
        Console.WriteLine("任务执行中...");
        Thread.Sleep(500);
    }
}, cts.Token);

Thread.Sleep(2000);
cts.Cancel(); // 取消任务

2. 线程优先级设置

Thread priorityThread = new Thread(() => 
{
    Console.WriteLine("高优先级线程执行");
});
priorityThread.Priority = ThreadPriority.Highest;
priorityThread.Start();

3. 线程本地存储

// 使用ThreadLocal实现线程本地存储
ThreadLocal<int> threadLocal = new ThreadLocal<int>(() => 42);

Thread t1 = new Thread(() => 
{
    threadLocal.Value = 100;
    Console.WriteLine($"线程1的值: {threadLocal.Value}");
});

Thread t2 = new Thread(() => 
{
    threadLocal.Value = 200;
    Console.WriteLine($"线程2的值: {threadLocal.Value}");
});

t1.Start();
t2.Start();
t1.Join();
t2.Join();

Console.WriteLine($"主线程的值: {threadLocal.Value}");

五、异步编程模型

1. async/await模式

// 使用async/await进行异步编程
async Task AsyncMethod()
{
    Console.WriteLine($"开始异步方法,线程ID:{Thread.CurrentThread.ManagedThreadId}");
    await Task.Run(() => 
    {
        Console.WriteLine($"异步任务中,线程ID:{Thread.CurrentThread.ManagedThreadId}");
        Thread.Sleep(1000);
    });
    Console.WriteLine($"异步方法完成,线程ID:{Thread.CurrentThread.ManagedThreadId}");
}

await AsyncMethod();

2. 并行任务处理

// 使用Parallel.For并行处理
Parallel.For(0, 10, i => 
{
    Console.WriteLine($"并行迭代{i},线程ID:{Thread.CurrentThread.ManagedThreadId}");
});

六、线程同步机制

1. lock关键字

// 使用lock实现线程同步
object lockObj = new object();
int sharedValue = 0;

List<Task> tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
    tasks.Add(Task.Run(() => 
    {
        lock (lockObj)
        {
            sharedValue++;
            Console.WriteLine($"当前值: {sharedValue}");
        }
    }));
}
Task.WaitAll(tasks.ToArray());

2. Monitor类

// 使用Monitor实现更灵活的同步
object monitorObj = new object();
bool lockTaken = false;

try
{
    Monitor.Enter(monitorObj, ref lockTaken);
    // 临界区代码
    Console.WriteLine("Monitor保护的代码区域");
}
finally
{
    if (lockTaken)
    {
        Monitor.Exit(monitorObj);
    }
}

3. Semaphore信号量

// 使用Semaphore控制并发访问
SemaphoreSlim semaphore = new SemaphoreSlim(3); // 允许3个并发

List<Task> semaphoreTasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
    semaphoreTasks.Add(Task.Run(async () => 
    {
        await semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"任务{Task.CurrentId}进入,当前计数: {semaphore.CurrentCount}");
            await Task.Delay(1000);
        }
        finally
        {
            semaphore.Release();
            Console.WriteLine($"任务{Task.CurrentId}离开");
        }
    }));
}
await Task.WhenAll(semaphoreTasks);

七、最佳实践总结

  1. 选择适当的线程模型
  • CPU密集型任务:考虑使用Parallel.For/ForEach
  • I/O密集型任务:优先使用async/await
  • 长时间后台任务:使用Task.Run或专用Thread
  1. 线程资源管理
   // 推荐使用Task.Factory配置长期运行任务
   Task longRunning = Task.Factory.StartNew(() => 
   {
       // 长时间运行的操作
   }, TaskCreationOptions.LongRunning);
  1. 异常处理
   try
   {
       Task faultedTask = Task.Run(() => throw new Exception("测试异常"));
       faultedTask.Wait();
   }
   catch (AggregateException ae)
   {
       foreach (var e in ae.InnerExceptions)
       {
           Console.WriteLine($"捕获异常: {e.Message}");
       }
   }
  1. 性能考量
  • 避免过度创建线程(线程上下文切换开销)
  • 合理设置线程池大小:
   ThreadPool.SetMinThreads(50, 50); // 根据应用需求调整
   ThreadPool.SetMaxThreads(500, 500);
  1. 现代替代方案
  • 对于新项目优先考虑async/await模式
  • 使用ValueTask优化高频调用的异步方法
  • 考虑使用System.Threading.Channels进行生产者-消费者模式

八、各方法对比表

方法类型典型使用场景优点缺点
Thread需要精细控制的长期后台任务完全控制优先级、状态创建开销大,管理复杂
ThreadPool短生命周期任务自动管理,资源利用率高无法控制具体线程
Task大多数并发场景功能丰富,支持async/await配置不当可能导致死锁
async/awaitI/O密集型操作代码简洁,避免回调地狱需要全链路支持异步
Parallel数据并行处理自动负载均衡不适合任务间有依赖的情况

九、代码示例:综合线程应用

// 综合示例:并行处理+异步I/O+结果聚合
async Task ProcessDataAsync(List<string> urls)
{
    var downloadTasks = urls.Select(async url => 
    {
        using var client = new HttpClient();
        string content = await client.GetStringAsync(url);
        return content.Length;
    }).ToList();

    int[] results = await Task.WhenAll(downloadTasks);
    Console.WriteLine($"总下载字符数: {results.Sum()}");
}

// 调用示例
await ProcessDataAsync(new List<string> 
{
    "https://example.com",
    "https://example.org",
    "https://example.net"
});

通过以上多种线程启动和控制方式,C#开发者可以根据具体场景选择最适合的并发编程模型,构建高效可靠的应用程序。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞49 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容