C#多线程编程
Posted 面向对象程序设计课程小助手
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#多线程编程相关的知识,希望对你有一定的参考价值。
NO.1 使用线程的理由
1
可以使用线程将代码同其他代码隔离,提高应用程序的可靠性;
2
可以使用线程来简化编码;
3
可以使用线程来实现并发执行。
NO.2 基本知识
1
进程与线程:进程作为操作系统执行程序的基本单位,拥有应用程序的资源,进程包含线程,进程的资源被线程共享,线程不拥有资源;
2
前台线程和后台线程:通过Thread类新建线程默认为前台线程。当所有前台线程关闭时,所有的后台线程也会被直接终止,不会抛出异常;
3
挂起(Suspend)和唤醒(Resume):由于线程的执行顺序和程序的执行情况不可预知,所以使用挂起和唤醒容易发生死锁的情况,在实际应用中应该尽量少用;
4
阻塞线程(Join):阻塞调用线程,直到该线程终止;
5
终止线程:
1)Abort:抛出 ThreadAbortException 异常让线程终止,终止后的线程不可唤醒。
2)Interrupt:抛出 ThreadInterruptException 异常让线程终止,通过捕获异常可以继续执行。
6
线程优先级:
1)AboveNormal;
2)BelowNormal;
3)Highest;
4)Lowest;
5)Normal,默认为Normal;
NO.3 线程的使用
线程函数通过委托传递,可以不带参数,也可以带参数(只能有一个参数),可以用一个类或结构体封装参数。
namespace Test
{ class Program
{ static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(TestMethod));
Thread t2 = new Thread(new ParameterizedThreadStart(TestMethod));
t1.IsBackground = true;
t2.IsBackground = true;
t1.Start();
t2.Start("hello");
Console.ReadKey();
} public static void TestMethod()
{
Console.WriteLine("不带参数的线程函数");
} public static void TestMethod(object data)
{ string datastr = data as string;
Console.WriteLine("带参数的线程函数,参数为:{0}", datastr);
}
}
}
NO.4 线程池
由于线程的创建和销毁需要耗费一定的开销,过多的使用线程会造成内存资源的浪费,出于对性能的考虑,于是引入了线程池的概念。线程池维护一个请求队列,线程池的代码从队列提取任务,然后委派给线程池的一个线程执行,线程执行完不会被立即销毁,这样既可以在后台执行任务,又可以减少线程创建和销毁所带来的开销。
线程池线程默认为后台线程(IsBackground)。
namespace Test
{ class Program
{ static void Main(string[] args)
{ //将工作项加入到线程池队列中,这里可以传递一个线程参数
ThreadPool.QueueUserWorkItem(TestMethod, "Hello");
Console.ReadKey();
} public static void TestMethod(object data)
{ string datastr = data as string;
Console.WriteLine(datastr);
}
}
}
NO.5 委托异步执行
委托的异步调用:BeginInvoke() 和 EndInvoke()
namespace Test
{ public delegate string MyDelegate(object data); class Program
{ static void Main(string[] args)
{
MyDelegate mydelegate = new MyDelegate(TestMethod);
IAsyncResult result = mydelegate.BeginInvoke("Thread Param", TestCallback, "Callback Param"); //异步执行完成
string resultstr = mydelegate.EndInvoke(result);
} //线程函数
public static string TestMethod(object data)
{ string datastr = data as string; return datastr;
} //异步回调函数
public static void TestCallback(IAsyncResult data)
{
Console.WriteLine(data.AsyncState);
}
}
}
NO.6 线程同步
1
原子操作(Interlocked):所有方法都是执行一次原子读取或一次写入操作。
2
lock()语句:避免锁定public类型,否则实例将超出代码控制的范围,定义private对象来锁定。
3
Monitor实现线程同步
通过Monitor.Enter() 和 Monitor.Exit()实现排它锁的获取和释放,获取之后独占资源,不允许其他线程访问。
还有一个TryEnter方法,请求不到资源时不会阻塞等待,可以设置超时时间,获取不到直接返回false。
4
ReaderWriterLock
当对资源操作读多写少的时候,为了提高资源的利用率,让读操作锁为共享锁,多个线程可以并发读取资源,而写操作为独占锁,只允许一个线程操作。
以上是关于C#多线程编程的主要内容,如果未能解决你的问题,请参考以下文章