-
Notifications
You must be signed in to change notification settings - Fork 4.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Expose method on PeriodicTimer to adjust interval #60384
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @mangod9 Issue DetailsBackground and motivationAfter discovering the new If the period between ticks is a constant interval the class is fine. However, if you have a sliding window where the period between ticks might increase (such is the case with something like an exponential backoff) you are forced to move back to using To provide a real-world example of this, lets say I have a remote service where a client request a temporary lease to gain access to that service. The lease contains a TTL, and it is up to the client to renew the lease before that TTL comes to pass. Upon renewal, the service returns a new TTL which may be longer or shorter depending on the clients reputation. It isn't possible today to use // rate based on the TTL the remote service gave us.
using var timer = new PeriodicTimer(RenewalTickRate);
while (await timer.WaitForNextTickAsync(_cancellationToken)) {
var response = await client.RenewLease(...);
Console.WriteLine($"New Lease TTL: {response.Ttl}");
// no way to adjust the timer to tick based on the new ttl
} You can accomplish this with API Proposalnamespace System.Threading
{
public sealed class PeriodicTimer : System.IDisposable
{
public PeriodicTimer(System.TimeSpan period) { }
public System.Threading.Tasks.ValueTask<bool> WaitForNextTickAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; }
public void Dispose() { }
+ public void Change(TimeSpan period);
}
} API Usage// rate based on the TTL the remote service gave us.
using var timer = new PeriodicTimer(RenewalTickRate);
while (await timer.WaitForNextTickAsync(_cancellationToken)) {
var response = await client.RenewLease(...);
timer.Change(response.Ttl);
} RisksNone I can immediately think of.
|
@stephentoub looks like you added this originally - #53899 - and @davidfowl you proposed it. Any concerns with this API proposal - could I mark as ready for review? (talked to @andrewmd5 about it offline) |
The concept seems fine. There are a variety of ways it could be surfaced, e.g. we might consider instead a get/set property. |
Yep. This looks fine, we can go to api review. |
why not a |
Was thinking that it may be a nice addition to be able to create a periodic timer given a cron expression. I know that (AFAIK) there's no built in support for cron as of now, but I'm dropping this here to see what other people thinks of it |
This is what I meant by "There are a variety of ways it could be surfaced, e.g. we might consider instead a get/set property."
That is a very different and much more complicated feature. Please open a separate issue if it's something you're interested in. Thanks. |
🍝 One possible advantage of the property approach would be making it easy to change the period by a relative amount of time (eg. |
Any progress on this proposal? |
It's in the queue to be reviewed. |
What will happen if the
|
It'd be "(2) The ValueTask will complete after a shortened or prolonged timespan, according to the delta of the changed Period", noting that there's of course a race condition between the timer firing in response to the current period and the new period taking effect. |
Yep, makes sense. What about the case that the |
Presumably ODE. Why are you asking? |
Because it is a useful API that I could make use of. Clarifying these details might make the process of approval smoother. :-) |
namespace System.Threading;
public partial class PeriodicTimer
{
public TimeSpan Period { get; set; }
} |
@stephentoub Will this property be exposed in .NET 8 or is there a possibility to use this already in .NET 7? |
Only .NET 8 and beyond. |
EDITED by @stephentoub on 9/1/2022 to update proposal
namespace System.Threading { public sealed class PeriodicTimer : System.IDisposable { public PeriodicTimer(System.TimeSpan period) { } public System.Threading.Tasks.ValueTask<bool> WaitForNextTickAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; } public void Dispose() { } + public TimeSpan Period { get; set; } } }
Background and motivation
After discovering the new
PeriodicTimer
class that was introduced in .NET 6 I tried to use it in a very simple implementation.If the period between ticks is a constant interval the class is fine. However, if you have a sliding window where the period between ticks might increase (such is the case with something like an exponential backoff) you are forced to move back to using
Task.Delay
To provide a real-world example of this, lets say I have a remote service where a client request a temporary lease to gain access to that service. The lease contains a TTL, and it is up to the client to renew the lease before that TTL comes to pass. Upon renewal, the service returns a new TTL which may be longer or shorter depending on the clients reputation.
It isn't possible today to use
PeriodicTimer
to create a background task that handles that renewal logic without explicitly creating a new instance or using gotos (implicit):You can accomplish this with
Task.Delay
by updating variables outside of awhile
loop, and I'm sure that is a pattern you can find in thousands of C# codebases, but then you lose out on the performance benefitsPeriodicTimer
offers. That being said, the underlyingTimerQueueTimer
that an instance ofPeriodicTimer
uses already supports changing its state, so I hope this isn't too major of a change to consider.API Proposal
namespace System.Threading { public sealed class PeriodicTimer : System.IDisposable { public PeriodicTimer(System.TimeSpan period) { } public System.Threading.Tasks.ValueTask<bool> WaitForNextTickAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; } public void Dispose() { } + public void Change(TimeSpan period); } }
API Usage
Risks
None I can immediately think of.
The text was updated successfully, but these errors were encountered: