在特定时间间隔调用方法
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.Threading
的 Timer
:
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()
.
时该调用将被取消
我需要 运行 特定时间间隔内的方法。如何通过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.Threading
的 Timer
:
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()
.