AutoResetEvent在Set之后立即重置
考虑以下模式:
private AutoResetEvent signal = new AutoResetEvent(false); private void Work() { while (true) { Thread.Sleep(5000); signal.Set(); //has a waiting thread definitely been signaled by now? signal.Reset(); } } public void WaitForNextEvent() { signal.WaitOne(); }
此模式的目的是允许外部消费者等待某个事件(例如 – 消息到达)。 不从类中调用WaitForNextEvent
。
举一个应该熟悉的例子,考虑System.Diagnostics.Process
。 它公开了一个Exited
事件,但它也公开了一个WaitForExit
方法,该方法允许调用者同步等待,直到进程退出。 这就是我想在这里实现的目标。
我需要signal.Reset()
的原因是,如果一个线程在 signal.Reset()
被调用之后调用signal.Reset()
换句话说,如果没有线程在等待时调用.Set
),它会立即返回,如同事件已经预先发出信号。
这个问题
而不是使用AutoResetEvent
或ManualResetEvent
,使用此:
public sealed class Signaller { public void PulseAll() { lock (_lock) { Monitor.PulseAll(_lock); } } public void Pulse() { lock (_lock) { Monitor.Pulse(_lock); } } public void Wait() { Wait(Timeout.Infinite); } public bool Wait(int timeoutMilliseconds) { lock (_lock) { return Monitor.Wait(_lock, timeoutMilliseconds); } } private readonly object _lock = new object(); }
然后改变你的代码:
private Signaller signal = new Signaller(); private void Work() { while (true) { Thread.Sleep(5000); signal.Pulse(); // Or signal.PulseAll() to signal ALL waiting threads. } } public void WaitForNextEvent() { signal.Wait(); }
没有保证。 这个:
AutoResetEvent flag = new AutoResetEvent(false); new Thread(() => { Thread.CurrentThread.Priority = ThreadPriority.Lowest; Console.WriteLine("Work Item Started"); flag.WaitOne(); Console.WriteLine("Work Item Executed"); }).Start(); // For fast systems, you can help by occupying processors. for (int ix = 0; ix < 2; ++ix) { new Thread(() => { while (true) ; }).Start(); } Thread.Sleep(1000); Console.WriteLine("Sleeped"); flag.Set(); // Decomment here to make it work //Thread.Sleep(1000); flag.Reset(); Console.WriteLine("Finished"); Console.ReadLine();
不会在我的系统上打印“已执行工作项”。 如果我在Set
和Reset
之间添加Thread.Sleep
,则打印它。 请注意,这与处理器有关,因此您可能必须创建大部分线程来“填充”CPU。 请注意,在我的电脑上,50%的时间可以重现:-)
对于退出:
readonly object mylock = new object();
然后在某个地方:
lock (mylock) { // Your code goes here }
和WaitForExit
:
void WaitForExit() { lock (mylock) ; // exited } void bool IsExited() { bool lockTacken = false; try { Monitor.TryEnter(mylock, ref lockTacken); } finally { if (lockTacken) { Monitor.Exit(mylock); } } return lockTacken; }
请注意, lock
构造与async
/ await
不兼容(因为几乎不是.NET的所有锁定原语)
我会使用TaskCompletionSource
:
private volatile TaskCompletionSource signal = new TaskCompletionSource (); private void Work() { while (true) { Thread.Sleep(5000); var oldSignal = signal; signal = new TaskCompletionSource () //has a waiting thread definitely been signaled by now? oldSignal.SetResult(0); } } public void WaitForNextEvent() { signal.Task.Wait(); }
在代码调用SetResult
,没有新代码进入TaskCompletionSource
可以获得正在发信号通知的TaskCompletionSource
。
我相信它不能保证。
但是,我不了解您的逻辑流程。 如果您的主线程Set
信号,为什么要等到该信号到达目的地? 在那个正在等待的线程中继续你的“信号设置”逻辑不是更好吗?
如果你不能这样做,我建议你使用第二个WaitHandle
来通知第一个线程第二个线程已经发出信号。 但我看不到这种策略的任何优点。
上述就是C#学习教程:AutoResetEvent在Set之后立即重置分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/989318.html