在特定时间间隔调用方法

Calling a method in specific interval

我需要 运行 特定时间间隔内的方法。如何通过c#

实现

我写了一个代码,但是没有重复。它只执行一次。 谁能向我解释什么是可观察和取消标记。使用方法

IObservable<long> observable = Observable.Interval(TimeSpan.FromHours(1));
System.Threading.CancellationTokenSource source = new System.Threading.CancellationTokenSource();
observable.Subscribe(x =>
{
    System.Threading.Tasks.Task task = sampleMethod();
    task.Start();
}, source.Token);

Observable.Interval(TimeSpan.FromHours(1)).SelectMany(_ => sampleMethod()).Subscribe()。暂时忽略取消行为(很容易添加),您只需将 Interval 正确映射到表示为 Task 的异步例程(内部处理为 IObservable<>,顺便说一句是 .ToObservable() 转换 Task 的扩展方法)。请注意,SelectMany(...) 在这里非常重要:否则 Rx 框架将不会等待 Task 完成,不会捕获可能的异常,也不会保留事件的原始顺序。

CancellationToken用于退订你编的Observable。从某种意义上说,它类似于 IDisposable,两者都服务于相同的目标:停止并清理您的订阅。因此,一旦您在其上调用 Cancel(),您将不会获得任何更新。

P.S。你确定 FromHours(1) 是正确的吗?你可能想要更少更长的间隔,例如 FromMinutre(1)

您可以通过多种方式实现这一点。最简单的方法之一是这样的:

public async Task RunScheduleJob(CancellationToken token)
{
  while(!token.IsCancellationRequest)
  {
    YourMethod();
    await Task.Delay(TimeSpan.FromHours(1), token)
  }
}

PS。对于这样一个简单的工作,您不需要使用 Reactive Extensions 或任何其他外部库。您可以通过 Task 个实例

来实现它

如果您只需要定时器功能,则不需要 Rx。您可以使用来自 System.ThreadingTimer:

    var timer = new Timer(_ =>
    {
        // repeating code goes here
        // the argument is an optional state that you can pass into the constructor
    });
    timer.Change( dueTime: TimeSpan.FromSeconds(1), period: TimeSpan.FromSeconds(0.1));
    // run your app
    timer.Dispose();

Timer 的优点是它允许您随时重新配置它(如果您想更改周期,只需再次调用 Change),暂时禁用它并彻底删除它(调用 Dispose)。

Rx 是处理这种情况的好方法。超级干净。

你问题中最基本的代码重写是这样的:

IObservable<Unit> observable =
    from i in Observable.Interval(TimeSpan.FromHours(1))
    from t in Observable.FromAsync(() => sampleMethod())
    select t;

IDisposable subscription = observable.Subscribe();

不需要取消令牌,因为您只需调用 subscription.Dispose() 即可停止此订阅。

但是,如果您的 sampleMethod() 调用很长 - 运行 则调用 subscription.Dispose() 会停止可观察对象,但任务会 运行 完成。如果您也特别想停止任务,那么对任务的调用将需要使用取消令牌并使用它来停止自身。

您的调用代码将是这样的:

IObservable<Unit> observable =
    from i in Observable.Interval(TimeSpan.FromHours(1))
    from t in Observable.FromAsync(ct => sampleMethod(ct))
    select t;

唯一的区别是 FromAsync 调用将 CancellationToken 传递给 sampleMethod 调用,当您调用 subscription.Dispose().

时该调用将被取消