Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无功扩展定时器_C#_System.reactive - Fatal编程技术网

C# 无功扩展定时器

C# 无功扩展定时器,c#,system.reactive,C#,System.reactive,我有一个哈希集。Occasionlay,新值将添加到此哈希集。我想做的是让一个计时器在添加元素一分钟后将其从集合中移除 我仍然是新的接收,但这似乎是一个理想的场合使用它 我试过这样的方法: AddItem(string item) { _mySet.Add(item); var timer = Observable.Timer(TimeSpan.FromSeconds(60), _scheduler); timer .Take(1) .Do(item =>

我有一个哈希集。Occasionlay,新值将添加到此哈希集。我想做的是让一个计时器在添加元素一分钟后将其从集合中移除

我仍然是新的接收,但这似乎是一个理想的场合使用它

我试过这样的方法:

AddItem(string item)
{
  _mySet.Add(item);
  var timer = Observable.Timer(TimeSpan.FromSeconds(60), _scheduler);
  timer
      .Take(1)
      .Do(item => RemoveItem(item))
      .Subscribe(_ => Console.WriteLine("Removed {0}", item));
}
theCollection.ItemsAdded
    .SelectMany(x => Observable.Timer(TimeSpan.FromSeconds(60), _scheduler).Select(_ => x))
    .Subscribe(x => theCollection.Remove(x));
它似乎工作正常(通过了单元测试)


有人认为这种方法有什么不对吗?

对不起,我不是故意挑你的毛病,但是:

始终处理IDispobles

(编辑:好吧,我不知道今天早上我在咖啡里放了什么,但我的回答完全是胡说八道;我只留下上面的内容,因为一般来说,你确实想确保处理掉任何
IDisposable
,但为了弥补接下来的唠叨……)

Subscribe
的调用创建了一个您没有处理的订阅,因此对该方法的多次调用只会让越来越多的垃圾排队-现在在这种特定情况下,这不是世界末日,因为
计时器只触发一次,但仍然…Dispose

如果您真的想使用这种方法(我认为更好的方法是让一些正在运行的线程/任务“倾向于”您的值,在认为必要时删除),至少可以尝试以下类似的方法:

好吧,不要理会那些被剔除的废话。
可观察计时器的实现如下:

public static IObservable<long> Timer(TimeSpan dueTime)
{
    return s_impl.Timer(dueTime);
}
现在是
base.\u observer.OnNext
,这是设置为在计时器滴答声时触发的内部接收器,其中的
调用
,即:

private void Invoke()
{
    base._observer.OnNext(0L);
    base._observer.OnCompleted();
    base.Dispose();
}
所以是的。它会自动处理自己——而且不会有任何“延迟订阅”四处浮动


嗯……乌鸦很好吃|

如果您使用的是ReactiveUI,那么一个名为
ReactiveCollection
的类肯定会有帮助,您可以这样使用它:

AddItem(string item)
{
  _mySet.Add(item);
  var timer = Observable.Timer(TimeSpan.FromSeconds(60), _scheduler);
  timer
      .Take(1)
      .Do(item => RemoveItem(item))
      .Subscribe(_ => Console.WriteLine("Removed {0}", item));
}
theCollection.ItemsAdded
    .SelectMany(x => Observable.Timer(TimeSpan.FromSeconds(60), _scheduler).Select(_ => x))
    .Subscribe(x => theCollection.Remove(x));
  • Do
    调用中的lambda看起来不正确-
    可观察。计时器
    生成int值,但您的集合是一个
    哈希集
    -这不应该编译。我猜这只是个打字错误

  • Do
    :通常,您的订阅应该在
    Subscribe
    中完成
    Do
    是针对副作用的(我不喜欢流中的副作用,所以我避免它,但它对调试很有用)

  • Take
    可观察。计时器在终止之前只产生一个值,因此不需要
    Take
    运算符

  • 我将把你的函数写成:

    AddItem(string item)
    {
        _mySet.Add(item);
        Observable.Timer(TimeSpan.FromSeconds(60), _scheduler)
            .Subscribe(_ => RemoveItem(item));
    }
    

    这样做不需要创建序列。你已经是一个好公民,并且明确地使用了调度器,所以就使用它吧

    你可以把它作为你的代码

    AddItem(string item)
    {
      _mySet.Add(item);
      //Note this does return an IDisposable if you want to cancel the subscription.
      _scheduler.Schedule(
        TimeSpan.FromSeconds(60),
        ()=>
        { 
            RemoveItem(item);
            Console.WriteLine("Removed {0}", item);
        });
    }
    
    这基本上意味着在幕后进行的工作要少得多。考虑所有可观察到的工作。计时器方法正在进行,当你只想让它做的是用一个值(你忽略)来调度一个ONNEXT。
    我还假设,即使是一个对Rx一无所知的用户也能够阅读此计划代码。ie.“添加此项目后,我计划在60秒内运行此删除操作)。

    嘿,杰克林巴勒,我认为在采取(1)之后满足后,源将自动释放。如果我添加一个未完成的处理程序,我会看到它被调用。调用未完成时,源是否已释放?@JerKimbal,这是错误的建议,请将其删除。在Rx上下文中IDisposable不需要处理。在Rx中,释放具有特殊含义,即提前断开订阅。没有内存泄漏,示例代码没有问题。抱歉@JerKimball,您通常对Rx很在行,但Paul和Flack是正确的-一旦序列完成,订阅将自动“处理”(取消订阅).哦,天哪,我真的很抱歉;我不知道我到底在想什么…你当然是对的-让我看看我是否可以通过一些编辑在这里重新获得一些面子…*facepalm*@AlexG我的羞耻感很好。我把这归咎于严重的头痛和最近的调试深入地狱。)哈哈。我只是指出,这与q中的代码实现了相同的结果问题不是问他如何切换到一个新的库并“更具功能”。正如Flack在问题中指出的,原始代码可以工作并通过单元测试。我只是建议他不需要使用序列。你认为AddItem(“foo”);会有什么样的行为……30秒后AddItem(“foo”)?
    AddItem(string item)
    {
      _mySet.Add(item);
      //Note this does return an IDisposable if you want to cancel the subscription.
      _scheduler.Schedule(
        TimeSpan.FromSeconds(60),
        ()=>
        { 
            RemoveItem(item);
            Console.WriteLine("Removed {0}", item);
        });
    }