下边有个 循环调用线程写奇偶数的程序
class TheadTest { //定义一个Stream对象接收打开文件 private FileStream st; //构造方法 public TheadTest() { } public void Start() { //定义两个信号锁 AutoResetEvent ateA = new AutoResetEvent(false); AutoResetEvent ateB = new AutoResetEvent(false); //把信号锁加入到List中 List<AutoResetEvent> lst = new List<AutoResetEvent>(); lst.Add(ateA); lst.Add(ateB); //定义带参数的输出偶数线程 Thread thrEven = new Thread(new ParameterizedThreadStart(OutPutEven)); thrEven.Name = "偶数线程"; //把两个信号锁传入线程 thrEven.Start(lst); //定义带参数的输出奇数线程 Thread thrOdd = new Thread(new ParameterizedThreadStart(OutPutOdd)); thrOdd.Name = "极数线程"; thrOdd.Start(lst); } private void OutPutEven(object lst) { AutoResetEvent ateA = (lst as List<AutoResetEvent>)[0]; AutoResetEvent ateB = (lst as List<AutoResetEvent>)[1]; for (int i = 0; i < 100; i += 2) { //设置本线程为无信号 ateA.WaitOne(); //输出 Console.WriteLine(i); //st = File.Open(@"C:/file.txt", FileMode.Open); //用来测试同时访问文件系统的 //st.Close(); ateB.Set(); //设置输出奇数线程有信号 //Thread.Sleep(500); } } private void OutPutOdd(object lst) { AutoResetEvent ateA = (lst as List<AutoResetEvent>)[0]; AutoResetEvent ateB = (lst as List<AutoResetEvent>)[1]; //设置偶数线程先输出 ateA.Set(); for (int i = 1; i < 100; i += 2) { //设置本线程为无信号 ateB.WaitOne(); Console.WriteLine(10000); //st = File.Open(@"C:/file.txt", FileMode.Open); //用来测试同时访问文件系统的 //st.Close(); ateA.Set(); //设置输出偶数线程有信号 //Thread.Sleep(500); } } }
此时两个线程执行方法都在循环中没问题 ,程序是交互进行的,ateA 先执行,然后waitone ,等待ateB执行完发送set信号。
把其中一个循环去掉,
// for (int i = 1; i < 100; i += 2) // { //设置本线程为无信号 ateB.WaitOne(); Console.WriteLine(10000); //st = File.Open(@"C:/file.txt", FileMode.Open); //用来测试同时访问文件系统的 //st.Close(); ateA.Set(); //设置输出偶数线程有信号 //Thread.Sleep(500); // }运行结果:
就运行了三行拉倒了,而且是
ateA 运行了两次,
ateB运行了一次。 没有循环只运行了一次,线程就结束了。
ateA 的循环即使发送
ateB.set()信号也没用了,线程已经关闭了,运行一次就关闭了,这里有些挺不爽的,也不知道是不是偶孤陋寡闻。从理解的角度上讲,线程应该一直在那启动着,给予set信号,线程执行程序开始运行,执行完后等待下次set信号,而不应该退出。所以要想用上这个知识点在程序中,还需要改进不少。这个问题上次处理上位机时碰到,当时已经知道这个问题,今天因为上边的写法中,参数和加了一个循环,导致自己出现错觉了,以为这种写法就可以给信号执行,没信号不执行,执行完之后线程挂起而不是退出的功能。
时间: 2024-10-29 10:46:35