学习C#异步编程
"杨老师视频教程"
P1 线程(Thread):创建线程视频地址
什么是线程Thread
线程是一个可执行路径,它可以独立于其它线程执行
每个线程都在操作系统的进程(Process)内执行,而操作系统进程提供了程序运行的独立环境。
单线程应用,在进程的独立环境里 只跑一个线程,所以该线程拥有独占权。
多线程应用,单个进程中会跑多个线程,它们会共享当前的执行环境(尤其是内存)
例如,一个线程在后台读取数据,另一个线程在数据到达后进行展示。
这个数据就被称作是共享的状态。
例子:
class Program { static void Main(string[] args) { Thread thread = new Thread(WriteY); //开启一个新的线程 Thread thread.Name = "Y Thread..."; thread.Start(); for (int i = 0; i < 1000; i++) Console.WriteLine("x"); Console.ReadKey(); } private static void WriteY() { for(int i = 0; i < 1000; i++) { Console.WriteLine("y"); } } }在单核计算机上,操作系统必须为每个线程分配“时间片”(在Windows中通常为20毫秒)来模拟并发,从而导致重复的x和y块。
在多核或多处理器计算机上,这两个线程可以真正地并行执行(可能受到计算机上其他活动进程的竞争)。
术语:线程被抢占线程在什么时候可以称为被抢占了:它的执行与另一个线程上代码的执行交织的那一刻。
线程的一些属性线程一旦开始执行,IsAlive就是true,线程结束就变成false。
线程结束的条件就是:线程构造函数传入的委托结束了执行。
线程一旦结束,就无法再重启。
每个线程都有个Name属性,通常用于调试
线程Name只能设置一次,以后更改会抛出异常。(System.InvalidOperationException:“该属性已经设置,不能修改。”)
静态的Thread.CurrentThread属性,会返回当前执行的线程。
P2 Thread.Join()&Thread.Sleep()视频地址
Join and Sleep
调用Join方法,就可以等待另一个线程结束。
例子:
class Program { static void Main(string[] args) { Thread t = new Thread(WriteY); t.Start(); t.Join();//当前线程会等待t线程执行结束 Console.WriteLine("线程结束"); Console.Read(); } private static void WriteY() { for(int i = 0; i < 1000; i++) { Console.Write("y"); } } } class Program { static Thread thread1, thread2; static void Main(string[] args) { thread1 = new Thread(ThreadProc); thread1.Name = nameof(thread1); thread1.Start(); thread2 = new Thread(ThreadProc); thread2.Name = nameof(thread2); thread2.Start(); Console.Read(); } private static void ThreadProc() { Console.WriteLine($"\nCurrent Thread:{Thread.CurrentThread.Name}"); if (Thread.CurrentThread.Name == nameof(thread1) && thread2.ThreadState != ThreadState.Unstarted) thread2.Join(); Thread.Sleep(4000); Console.WriteLine($"\nCurrent thread:{Thread.CurrentThread.Name}"); Console.WriteLine($"Thread1:{thread1.ThreadState}"); Console.WriteLine($"Thread2:{thread2.ThreadState}"); } }输出内容:
Current Thread:thread1
Current Thread:thread2
Current thread:thread2
Thread1:WaitSleepJoin
Thread2:Running
Current thread:thread1
Thread1:Running
Thread2:Stopped
调用Join的时候,可以设置一个超时,用毫秒或者TimeSpan都可以。
如果返回true,那就是线程结束了,如果超时了,就返回false。
例子:
class Program { static Thread thread1, thread2; static void Main(string[] args) { thread1 = new Thread(ThreadProc); thread1.Name = nameof(thread1); thread1.Start(); thread2 = new Thread(ThreadProc); thread2.Name = nameof(thread2); thread2.Start(); Console.Read(); } private static void ThreadProc() { Console.WriteLine($"\nCurrent Thread:{Thread.CurrentThread.Name}"); if (Thread.CurrentThread.Name == nameof(thread1) && thread2.ThreadState != ThreadState.Unstarted) if (thread2.Join(2000)) Console.WriteLine("线程2结束"); else Console.WriteLine("线程2超时了"); Thread.Sleep(4000); Console.WriteLine($"\nCurrent thread:{Thread.CurrentThread.Name}"); Console.WriteLine($"Thread1:{thread1.ThreadState}"); Console.WriteLine($"Thread2:{thread2.ThreadState}"); } }输出:
Current Thread:thread1
Current Thread:thread2
线程2超时了
Current thread:thread2
Thread1:WaitSleepJoin
Thread2:Running
Current thread:thread1
Thread1:Running
Thread2:Stopped
Thread.Sleep()方法会暂停当前的线程,并等待一段时间。
注意:
Thread.Sleep(0)这样调用会导致线程立即放弃本身当前的时间片,自动将CPU移交给其他线程。
Thread.Yield()做同样的事情,但是它只会把执行交给同一处理器上的其它线程。
当等待Sleep或Join的时候,线程处于阻塞的状态。
Sleep(0)或Yield有时在高级性能调试的生产代码中很有用。它也是一个很好的诊断工具,有助于发现线程安全问题:
如果在代码中的任何地方插入Thread.Yield()就破坏了程序,那么你的程序几乎肯定有bug。
P3 阻塞Blocking视频地址
阻塞
如果线程的执行由于某种原因导致暂停,那么就认为该线程被阻塞了。
例如在Sleep或者通过Join等待其它线程结束。
被阻塞的线程会立即将其处理器的时间片生成给其它线程,从此就不再消耗处理器时间,直到满足其阻塞条件为止。
可以通过ThreadState这个属性来判断线程是否处于被阻塞的状态:
bool blocked = (thread.ThreadState & ThreadState.WaitSleepJoin) != 0; ThreadState
温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/43495.html