Csharp/C#教程:AutoResetEvent在Set之后立即重置分享


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 ),它会立即返回,如同事件已经预先发出信号。

这个问题

而不是使用AutoResetEventManualResetEvent ,使用此:

 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(); 

不会在我的系统上打印“已执行工作项”。 如果我在SetReset之间添加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

(0)
上一篇 2021年12月23日
下一篇 2021年12月23日

精彩推荐