多线程
一个应用程序至少包括一个进程,一个进程至少包括一个线程。程序需要在线程中执行,主线程由程序默认创建。单线程程序顺序执行,多线程程序同一时间可同时执行不同操作。
多线程的应用
线程的构造函数支持两种不同委托,一种不带参数的委托,一种带类型为object
的一个参数。
class Program ???{ ???????static void Main(string[] args) ???????{ ???????????ThreadStart ts = new ThreadStart(ThreadEntry); ???????????Thread worker = new Thread(ts); ???????????worker.Start(); ???????????ParameterizedThreadStart pts = new ParameterizedThreadStart(ThreadEntry); ???????????Thread worker1 = new Thread(pts); ???????????worker1.Start("Item4"); ???????????Console.WriteLine("Main Thread ends."); ???????????Console.ReadKey(); ???????} ???????static void ThreadEntry() ???????{ ???????????SharedResource resource = new SharedResource(); ???????????resource.Add("Item3"); ???????} ???????static void ThreadEntry(object item) ???????{ ???????????SharedResource resource = new SharedResource(); ???????????string strItem = (string)item; ???????????resource.Add(strItem); ???????} ???} ???public class SharedResource ???{ ???????public List<string> list = new List<string> { "Item0", "Item1", "Item2" }; ???????public void Add(string item) ???????{ ???????????Console.WriteLine("Add" + item); ???????????list.Add(item); ???????} ???}
线程的属性与方法
ManagedThreadId
托管线程id,进程内唯一Name
线程名称,默认为空,开发者设置(不可修改)ThreadState
线程状态Thread.CurrentThread
获取当前线程Thread.Sleep(1000);
线程睡眠1sworker.IsBackground = true;
设置线程为后台线程,线程默认为前台线程,前台线程结束不管后台线程是否结束程序就会结束。worker.Join();
线程阻塞,等待worker
线程执行结束线程同步
CLR为每个线程分配了线程栈,用于保存本地变量,这样线程可以保证本地变量是独立的。但是线程外的变量对多线程是共享的。 针对多线程访问共享资源带来的问题两种解决方式 线程锁与线程通信
* * *
多线程同时访问变量问题:同时修改一个资源???static void Print() ???{ ???????Console.WriteLine("i={0}",i); ???????Thread.Sleep(1000); ????????i++; ???} ???static void Main(string[] args) ???{ ???????ThreadStart ts1 = new ThreadStart(Print); ???????Thread th1 = new Thread(ts1); ???????th1.Start(); ???????Print(); ???????Console.ReadKey(); ???}
线程锁
线程锁:同一时间只允许单个线程访问代码区域。
?static object olock = new object(); ???static int i = 0; ???static void Main(string[] args) ???{ ???????ThreadStart ts1 = new ThreadStart(Print); ???????Thread th1 = new Thread(ts1); ???????th1.Start(); ???????Print(); ???????Console.ReadKey(); ???} ???static void Print() ???{ ???????lock (olock) ???????{ ???????????Console.WriteLine("i={0}", i); ???????????Thread.Sleep(1000); ???????????i++; ???????} ???}
lock
只能接受引用变量,并且应该保证变量唯一。线程信号
public class Resource{ ???public string Data;} class Program{ ???private Resource res = new Resource(); ???static void Main(string[] args) ???{ ???????Thread.CurrentThread.Name = "Main"; ???????Program p = new Program(); ???????Thread worker = new Thread(p.ThreadEntry1); ???????worker.Name = "Worker"; ???????worker.Start(); ???????lock (p.res) ???????{ ???????????if (string.IsNullOrEmpty(p.res.Data)) ???????????{ ???????????????//发送线程等待信号(Main线程等待) ???????????????Monitor.Wait(p.res); ???????????} ???????????Console.WriteLine("Data={0}",p.res.Data); ???????} ???????Console.ReadKey(); ???} ???void ThreadEntry1() ???{ ???????lock (res) ???????{ ???????????res.Data = "Retrived"; ???????????//发送线程开始执行信号(向主线程发送开始信号) ???????????Monitor.Pulse(res); ???????} ???}}
线程的处理类
更多线程处理的类,请查看
WaitHandle