> For the complete documentation index, see [llms.txt](https://docs.zongsoft.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zongsoft.com/documentation/en/framework/core/common/timer.md).

# Timer

Understand periodic callback, cancellation, stop and release through the existing TimerTest in the framework.

Timer is used to call asynchronous callback periodically. It is suitable for lightweight polling within the host; cross-process persistence scheduling and failure retries should read [Task scheduling](/documentation/en/framework/core/scheduling.md). Discussions There is no business example that directly uses timers. The existing tests of the framework are used here.

## Create Callbacks and Completion Signals

TimerTest sets the period to 1 millisecond and waits for the 10th callback with a completion signal. LIMIT, \_count, \_timer and \_completion are all members of this test fixture; the period is a test parameter, and the actual task needs to be configured based on the work time.

Source: [framework/Zongsoft.Core/test/Common/TimerTest.cs](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/test/Common/TimerTest.cs#L22) (excerpt; see source for context).

{% code title="TimerTest.cs" %}

```csharp
public TimerTest()
{
	_timer = new Timer(TimeSpan.FromMilliseconds(1), this.OnTick);
	_completion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
}
```

{% endcode %}

## Start and Wait for Completion

Source: [framework/Zongsoft.Core/test/Common/TimerTest.cs](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/test/Common/TimerTest.cs#L31) (excerpt; see source for context).

{% code title="TimerTest.cs" %}

```csharp
public async Task Test()
{
	Assert.False(_timer.IsRunning);
	_timer.Start(TestContext.Current.CancellationToken);
	Assert.True(_timer.IsRunning);

	await _completion.Task.WaitAsync(TimeSpan.FromSeconds(30), TestContext.Current.CancellationToken);
	Assert.Equal(LIMIT, _count);
	Assert.False(_timer.IsRunning);
}
```

{% endcode %}

The test checks IsRunning before start, after start, and after end. The wait limit of 30 seconds is used to prevent failed tests from hanging indefinitely and does not represent timer accuracy or business timeout commitments.

## Stop in Callback

Source: [framework/Zongsoft.Core/test/Common/TimerTest.cs](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/test/Common/TimerTest.cs#L44) (excerpt; see source for context).

{% code title="TimerTest.cs" %}

```csharp
private ValueTask OnTick(object state, CancellationToken cancellation)
{
	if(Interlocked.Increment(ref _count) >= LIMIT)
	{
		_timer.Stop();
		_completion.TrySetResult();
	}

	return ValueTask.CompletedTask;
}
```

{% endcode %}

After the callback reaches LIMIT, Stop is called and the waiting party is notified. Stopping the cycle does not mean undoing the business side effects that have occurred; external operations in callbacks should still comply with their own cancellation and idempotent conventions.

{% hint style="info" %}
💡 The component that created the timer should be responsible for eventually releasing it. On target frameworks that support runtime setting of Period, subsequent periods can be adjusted; see [Timer.cs](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/src/Common/Timer.cs) for the actual conditional compilation and release logic.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.zongsoft.com/documentation/en/framework/core/common/timer.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
