如何让线程等待,直到变量达到 .NET/Csharp 中的一组值之一
我编写了一个类,该类具有 TProperty
类型的属性和 Action
类型的事件,每当该属性发生更改时就会触发该事件。 TProperty
通常是枚举类型,但这并不重要。
我想创建一个带有签名的方法
bool WaitUntilPropertyIs(int TimeoutMs, IEnumerable<TProperty> AllowedValues)
,该方法会阻止调用它的线程,直到属性更改为 AllowedValues
中的值。当然,如果在属性已经是AllowedValues之一时调用WaitUntilPropertyIs,则不应出现阻塞。 WaitUntilPropertyIs
最多应等待 TimeoutMs
并在超过超时时返回 false(正常的 AutoResetEvent.Wait
语义)。
我愿意使用反应式扩展或传统的同步结构。
I've written a class that has a property of type TProperty
and an event of type Action<TProperty>
that fires whenever that property changes. TProperty
is typically an enum type, but that shouldn't matter.
I'd like to create a method with signature
bool WaitUntilPropertyIs(int TimeoutMs, IEnumerable<TProperty> AllowedValues)
that blocks the thread that called it until the property changes to a value that is in AllowedValues
. Ofcourse if WaitUntilPropertyIs is called when the property is alread one of the AllowedValues
, there should be no blocking. WaitUntilPropertyIs
should wait at most TimeoutMs
and return false if the Timeout is exceeded (normal AutoResetEvent.Wait
semantics).
I'm open to using Reactive Extensions or traditional synchronization constructs.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
对于这种情况,Rx 就显得有些过分了。您可以通过
ManualResetEvent
或ManualResetEventSlim
来完成此操作。您可以将您的解决方案设计为以下内容:但我不知道您的确切要求,因此请考虑修改上面的代码以防止竞争条件。
Rx is overkill for this kind of scenario. You can do it via
ManualResetEvent
orManualResetEventSlim
. You can pattern your solution to the following:I don't know your exact requirements though so consider modifying the code above to protect against race conditions.
在 Rx + ReactiveUI 中,这是通过以下方式完成的:
如果我们想添加一个超时 + 一个 bool 来表示该属性已实际设置,我们可以这样做:
In Rx + ReactiveUI, this is accomplished via:
If we wanted to add a timeout + a bool signifying that the property is actually set, we could do this:
我决定将所有这些功能包装在一个类中,以便我可以在其他地方重用它。这段代码可以解决问题。
在构造函数中,传入 CurrentValueFunc,它必须根据需要返回监视变量的当前值,传入 IsValueAcceptableFunc,如果当前值可接受,它必须返回 true。
您需要确保每当值更改时都会调用 ValueWatcher.ValueUpdated。
I decided to wrap all of this functionality in a class so I can reuse it in other places. This code does the trick.
On the constructor, pass in CurrentValueFunc which must return the current value of the watched variable on demand, pass in IsValueAcceptableFunc which must return true if the current value is acceptable.
You need to ensure that ValueWatcher.ValueUpdated is called whenever the value changes.
一个“Waiter”类和一个列表样式的容器应该可以做到这一点。使用相同的关键部分锁定列表访问和属性设置器/事件/任何内容。服务员类只需要AllowedValues 和一个供调用者等待的事件(好吧,也许是一个“bool check(IEnumerable newAllowedValues)”帮助程序)。
应该是这样。在WaitUntilPropertyIs()中,获取CS并首先检查属性值,看看是否可以释放CS并立即返回,如果不能,调用者必须等待。创建一个服务员,复制传递的AllowedValues,将服务员添加到列表中,释放CS并在传递的超时时间内等待事件。当事件等待返回时,重新获取 CS,从列表中删除服务员,对其进行 dispose(),释放 CS 并从事件等待调用中返回 true/false。
在setter/Action/其他中,获取CS,迭代列表,与新的AllowedValues进行比较,在新值满足范围的任何服务员上触发任何事件,然后释放CS。
平均值,
马丁
A 'Waiter' class and a list-style container should do it. Lock up the list access and the property setter/event/whatever with the same Critical Section. The waiter class needs only the AllowedValues and an event for the callers to wait on, (OK, maybe a 'bool check(IEnumerable newAllowedValues)' helper).
That should be it. In WaitUntilPropertyIs(), acquire the CS and check against the property values first to see if it can just release the CS and return immediately, if not, the caller has to wait. Create a waiter, copy in the passed AllowedValues, add the waiter to the list, release the CS and wait on the event with the passed timeout. When the event wait returns, re-acquire the CS, remove the waiter from the list, dispose() it, release the CS and return with true/false from the event wait call.
In the setter/Action/whatever, acquire the CS, iterate the list, comparing with the new AllowedValues, fire any event on any waiter where the new values satisfy the range and then release the CS.
Rgds,
Martin
将该属性建模为
Behavior
(来自 Rx 的类,以及响应式编程中针对在一段时间内发生变化的值的一般概念)。Model that property as
Behavior
(class from Rx, and a general concept in reactive programming for values that changes over a period of time).