1.多线程的创建
1.1 使用Thread类创建线程
示例代码
using System;
using System.Threading;
class TraditionalThreadingDemo
{
static void Main(string[] args)
{
// 直接使用方法名创建线程
Thread thread1 = new Thread(MethodToRun);
thread1.Start();
// 使用Lambda表达式创建线程
Thread thread2 = new Thread(() => Console.WriteLine("Hello from Lambda thread"));
thread2.Start();
// 确保主线程等待子线程执行完毕
thread1.Join();
thread2.Join();
Console.WriteLine("All threads have finished.");
}
static void MethodToRun()
{
Console.WriteLine("Hello from traditional thread.");
}
}
- Thread 类创建线程:
- 传统线程创建方式,通过
new Thread
实例化线程对象,并指定一个ThreadStart
委托(指向要执行的方法)或直接使用Lambda表达式定义执行内容。调用Start
方法启动线程。 - 注意,使用
Thread
需要显式管理线程的生命周期,如使用Join
方法等待线程结束。
- 传统线程创建方式,通过
1.2. 使用Task进行异步编程
示例代码
using System;
using System.Threading.Tasks;
class ModernAsyncProgrammingDemo
{
static async Task Main(string[] args)
{
// 使用Task.Run进行异步操作
Task task1 = Task.Run(() => Console.WriteLine("Hello from Task 1"));
// 直接使用async/await进行异步调用
await Task.Run(() => Console.WriteLine("Hello from Task 2 asynchronously"));
// 等待所有任务完成,这里由于使用了await,Main方法会自然等待任务完成
await Task.WhenAll(task1);
Console.WriteLine("All tasks have finished.");
}
}
- Task 类进行异步编程:
-
Task.Run
方法可以用来启动一个新的任务(本质上也是基于线程池线程) -
两个Console.WriteLine调用几乎会同时开始。第一个Task.Run没有使用await,所以它不会阻塞主线程等待task1完成。而第二个操作由于使用了await,主线程会等待这个任务完成后再继续
-
Task.WhenAll
用于等待一组任务全部完成,常用于需要等待多个异步操作结束的场景。在上面的Main
方法中,因为使用了await
关键字,所以不需要显式调用类似Join
的方法等待任务完成,编译器会自动处理这一逻辑。
-
2.多线程的使用
2.1 向线程传递数据
方法1: 使用 lambda 表达式调用目标方法,在表达式内指定参数
static void Main()
{
Thread t = new Thread ( () => Print ("Hello from t!") );
t.Start();
}
static void Print (string message)
{
Console.WriteLine (message);
}
使用这种方式,可以向方法传递任意数量的参数。甚至可以将整个实现封装为一个多语句的 lambda 表达式:
new Thread (() =>
{
Console.WriteLine ("I'm running on another thread!");
Console.WriteLine ("This is so easy!");
}).Start();
方法2:向Thread的Start方法传递参数,只能传一个参数
static void Main()
{
Thread t = new Thread (Print);
t.Start ("Hello from t!");
}
static void Print (object messageObj)
{
string message = (string) messageObj; // 需要强制类型转换
Console.WriteLine (message);
}
2.2.线程的命名
class ThreadNaming
{
static void Main()
{
//设置主线程名字
Thread.CurrentThread.Name = "main";
Thread worker = new Thread (Go);
worker.Name = "worker";
worker.Start();
Go();
}
static void Go()
{
Console.WriteLine ("Hello from " + Thread.CurrentThread.Name);
}
}
2.3前后台线程
- 前台线程
默认情况下,主线程和通过 new Thread() 创建且未明确设置为后台线程的线程都是前台线程,前台线程对于进程的生命周期至关重要,只要还有任何前台线程在运行,进程就会持续运行。只有当所有前台线程都结束时,进程才会终止。
- 后台线程
可以通过将 Thread.IsBackground 属性设置为 true 来将一个线程标记为后台线程。
新建线程时,设定属性
var th = new Thread((obj) => //指定了线程的执行逻辑
{
try
{
Console.WriteLine(obj);
for (int i = 0; i < 20; i++)
{
Thread.Sleep(200);//子线程暂停
Console.WriteLine("Thred is still running...");
}
}
catch (ThreadInterruptedException)
{
}
finally
{
Console.WriteLine("Thread is finished");
}
}){IsBackground=true,Priority=ThreadPriority.Normal};