+ -
当前位置:首页 → 问答吧 → 请问,线程WaitOne方法Set方法什么意思啊

请问,线程WaitOne方法Set方法什么意思啊

时间:2011-12-07

来源:互联网

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);  
  ateB.Set(); //设置输出奇数线程有信号  
  }  
  }  

上面代码是一个线程执行的方法,我没有写完全代码,太多了
我想问,WaitOne方法Set方法是什么意思啊,MSDN上得解释很咬口
设置本线程为无信号?设置线程有信号 ?什么意思哦?

作者: ersrcdwer1   发布时间: 2011-12-07

WaitOne 和 Set 属于一对方法。

假设 AutoResetEvent 初始化为 true,就是已经占用了一个信号。
那么在 Set(释放信号) 方法没有被调用前,
WaitOne 会一直等到该信号量被释放
(如果成功获得信号则返回true,
 如果超时或者失败则返回false,WaitOne还可以传入参数设置等待超时时间)

应该还有一个方法是对 ateA.Set();

作者: fangxinggood   发布时间: 2011-12-07

上面代码是不是写错了?就代码本身看,这个ateA.WaitOne(); 要循环50次,但是你却用的是“ateB.Set();”,而不是“ateA.Set();”,因此循环了一次就卡住了,没有Set()信号,第二次WaitOne()就会卡住等待,但是这里始终看不到有Set会给啊。

作者: qldsrx   发布时间: 2011-12-07

全部代码:
class Program  
  {  
  static void Main(string[] args)  
  {  
  TheadTest th = new TheadTest();  
  th.Start();  
  Console.ReadKey();  
  }  
  }  
  /// <summary>  
  /// 定义一个线程类  
  /// </summary>  
  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.Start(lst);  
  
  //定义带参数的输出奇数线程  
  Thread thrOdd = new Thread(new ParameterizedThreadStart(OutPutOdd));  
  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(i);  
  //st = File.Open(@"C:/file.txt", FileMode.Open); //用来测试同时访问文件系统的  
  //st.Close();  
  ateA.Set(); //设置输出偶数线程有信号  
  //Thread.Sleep(500);  
  }  
  }  
  }

作者: ersrcdwer1   发布时间: 2011-12-07

MSDN

线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。 如果 AutoResetEvent 为非终止状态,则线程会被阻止,并等待当前控制资源的线程通过调用 Set 来通知资源可用。

调用 Set 向 AutoResetEvent 发信号以释放等待线程。 AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。 如果没有任何线程在等待,则状态将无限期地保持为终止状态。

如果当 AutoResetEvent 为终止状态时线程调用 WaitOne,则线程不会被阻止。 AutoResetEvent 将立即释放线程并返回到非终止状态。



哪位朋友能不能解释一下上面的话,我看不懂呢,可以用最最最通俗的话来解释
线程被释放?什么意思?

作者: ersrcdwer1   发布时间: 2011-12-07

AutoResetEvent就好象地铁闸门,你过去的时候刷一下卡,它让一个人过去,然后就会自动恢复为关闭状态。

假设开启操作是用电磁吸引控制的,那么关闭操作就是“无信号”。

作者: sp1234   发布时间: 2011-12-07

嗯,这个什么“无信号、有信号”的说法确实比较绕,而且完全可以反过来解释,所以这个解释看起来确实不靠谱。

其实Set的意思就直接用英文好了,还是根本避开“有信号、无信号”更加容易让程序员理解。

作者: sp1234   发布时间: 2011-12-07

线程阻塞成立的一对条件:
1.线程中包含waitone();
2.AutoResetEvent(bool)的bool为false,即事件状态为非终止状态;

set()方法是将事件状态设置为终止状态(其实就是破坏第2个条件),允许一个或多个等待线程继续。

作者: pyrtvu   发布时间: 2011-12-07

引用 5 楼 sp1234 的回复:
AutoResetEvent就好象地铁闸门,你过去的时候刷一下卡,它让一个人过去,然后就会自动恢复为关闭状态。

假设开启操作是用电磁吸引控制的,那么关闭操作就是“无信号”。


这个很明白了。

作者: csnd_freeman   发布时间: 2011-12-08

对这段话,我还是不明白


MSDN



线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。 如果 AutoResetEvent 为非终止状态,则线程会被阻止,并等待当前控制资源的线程通过调用 Set 来通知资源可用。

调用 Set 向 AutoResetEvent 发信号以释放等待线程。 AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。 如果没有任何线程在等待,则状态将无限期地保持为终止状态。

如果当 AutoResetEvent 为终止状态时线程调用 WaitOne,则线程不会被阻止。 AutoResetEvent 将立即释放线程并返回到非终止状态。


哪位朋友能不能解释一下上面的话,我看不懂呢,可以用最最最通俗的话来解释
线程被释放?什么意思?

作者: ersrcdwer1   发布时间: 2011-12-08

AutoResetEvent 有两种状态 一种终止状态,另一种 非终止状态

构造函数有个bool参数,true 是终止, false 是非终止

 WaitOne 是用来等待的,如果AutoResetEvent 处于 非终止状态 那么会一直等待,直至调用 Set

如果是终止状态 ,那么不会阻塞 会继续

调用 Set 就是告知 我的工作完成了,我现在可以走了 ,大家久等了.



作者: Sandy945   发布时间: 2011-12-08

引用 10 楼 sandy945 的回复:

AutoResetEvent 有两种状态 一种终止状态,另一种 非终止状态

构造函数有个bool参数,true 是终止, false 是非终止

WaitOne 是用来等待的,如果AutoResetEvent 处于 非终止状态 那么会一直等待,直至调用 Set

如果是终止状态 ,那么不会阻塞 会继续

调用 Set 就是告知 我的工作完成了,我现在可以走了 ,大家久等了……


真的很难懂啊,是不是和Monitor类的Pulse、Wait方法一个意思呢?
一个用于唤醒其他线程,一个用于阻止本线程
Monitor.Pulse();
Monitor.Wait();

作者: ersrcdwer1   发布时间: 2011-12-08

WaitOne()是用来等待线程的(挂起),Set()是用来设置线程信号状态可调用的的。当调用过Set()了以后,WaitOne()下面的代码会继续执行!

作者: vincent_void   发布时间: 2011-12-08

是不是和Monitor类的Pulse、Wait方法一个意思呢?
------------------------------------------
不太一样,但是能实现同样的功能,比如多个线程之间切换着执行 

可能我之前说到不准确,AutoResetEvent 是用于多线程之间的"调度",通过信号量来实现

如果有多个线程,共用一个AutoResetEvent ,那么调用WaitOne 方法的线程将会等待

如果是线程切换执行,那么应该是1个线程执行,其余的线程都调用 WaitOne 方法等待

当执行的线程调用 SET 方法时,会发出信号量 告知所有等待的线程可以执行

但只会有一个线程被执行,其余还是等待.  

作者: Sandy945   发布时间: 2011-12-08

C# code

Console.WriteLine("0");

AutoResetEvent autoResetEvent = new AutoResetEvent(false);

new Thread(_ => { for (int i = 1; i < 100; i += 2) { Console.WriteLine(i.ToString()); autoResetEvent.Set(); Thread.Sleep(1); } }).Start();
new Thread(_ => { for (int i = 2; i < 101; i += 2) { autoResetEvent.WaitOne(); Console.WriteLine(i.ToString()); } }).Start();

Console.ReadLine();

作者: Sandy945   发布时间: 2011-12-08

Thread.Sleep(1); 

是要让另外的线程有执行的机会,否则基数线程会连续执行.

WaitOne 这个方法是始终等待信号量,就是排队

作者: Sandy945   发布时间: 2011-12-08

引用 7 楼 pyrtvu 的回复:
线程阻塞成立的一对条件:
1.线程中包含waitone();
2.AutoResetEvent(bool)的bool为false,即事件状态为非终止状态;

set()方法是将事件状态设置为终止状态(其实就是破坏第2个条件),允许一个或多个等待线程继续。

楼主不要去想什么是AutoResetEvent的终止状态,什么是非终止状态,这样一点意义都没有,因为AutoResetEvent、waitonet和set()是结合在一起使用的,应该考虑什么情况下线程会阻塞,什么情况下会释放。还有自己也要把线程的概念给搞清楚。

作者: pyrtvu   发布时间: 2011-12-08

事实上楼上的很多兄弟已经讲的很清楚了,之前我也是被这个问题搞的很纠结。

作者: pyrtvu   发布时间: 2011-12-08

有个问题,我这样理解正确不?

Set()代码执行之后,WaintOne()后面的代码就要开始执行
Set的那个线程,发出了通知,WaintOne的那个线程接收到了通知,因为先前它一直阻塞在WaintOne()这句代码这里,一旦接到通知,WaintOne之后的代码,立刻开始执行。并且Set()之后的代码和WaintOne之后的代码是同时进行的


这样理解正确否?

作者: ersrcdwer1   发布时间: 2011-12-08

调用set 方法的线程是不在等待队列里的(因为它有机会set)

而在set 之前,其他的线程都回在 WaintOne 这句等待,

如果接受到set的信号,那么回从等待队列中选一个出来 ,其他线程继续等待.

直至下次set. 之前从等待队列出来的线程会持续执行,如果之后运行的代码中没有WaintOne的话

如果有的话,也会重新加入到等待的队列中.

之前调用set 的方法 是会一直执行的

作者: Sandy945   发布时间: 2011-12-08

恩,是这样啊

作者: chenandczh   发布时间: 2011-12-08

成对出现就对了
就像一个开关

作者: ohkuy   发布时间: 2011-12-08

对于ManualResetEvent和AutoResetEvent
你们通常叫的啥?

开关?监视器?信号?

作者: ersrcdwer1   发布时间: 2011-12-08

个人觉得叫调度器 更好一些

作者: Sandy945   发布时间: 2011-12-08