【问题标题】:ManualResetEvent to IObservable<bool> (or WaitHandle to IObservable<Unit> )?ManualResetEvent 到 IObservable<bool> (或 WaitHandle 到 IObservable<Unit> )?
【发布时间】:2017-06-01 10:14:50
【问题描述】:

我想基于 ManualResetEvent 的 Sets/Resets 创建一个 IObservable-stream,例如原则上类似于

IObservable<bool> ToObservable(ManualResetEvent ev)
{
  var s = new Subject<bool>();
  ev.OnSet += s.OnNext(true);
  ev.OnReset += s.OnNext(false);
  return s;
}

当然,只有 ManualResetEvent 不会公开此类事件。那么有什么方法可以观察它何时停止/重置?

作为记录,如果 set/unset 到 true/false 之间的区别是不可能的,更简单的 IObservable 在 ManualResetEvent 的状态发生变化时推送一个值也是可以的。

有什么办法吗?

我找到了一篇文章,解释了如何将 ManualResetEvent(或者更确切地说,一般来说是 WaitHandle)转换为任务(Wrapping ManualResetEvent as awaitable task),只要下次 ManualResetEvent 更改(从 set 到未设置,或其他方式)。 但是我还没有真正找到任何方法可以将其链接到一个序列中(例如,在任务完成后,我需要为下一个事件创建另一个,等等,并以某种方式创建一个可观察的“递归”序列)

谢谢!

【问题讨论】:

    标签: c# multithreading system.reactive


    【解决方案1】:

    有很多不同的方法可以做到这一点,但像这样:

    public static class ManualResetEventObservable
    {
        public static IObservable<bool> Create(ManualResetEvent e, TimeSpan timeout)
        {
            return Observable.Create<bool>(observer =>
            {
                var cancelEvent = new ManualResetEvent(false);
                var waitHandles = new[] { cancelEvent, e };
                var thread = new Thread(new ThreadStart(() =>
                {
                    var index = WaitHandle.WaitAny(waitHandles, timeout);
                    if (index == 1)
                        observer.OnNext(true);
    
                    observer.OnCompleted();
                }));
                thread.Start();
                return Disposable.Create(() => cancelEvent.Set());
            });
        }
    

    【讨论】:

    • 我会在最后一个 ; 之前添加 .Publish().RefCount()。这将确保资源的单一使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多