กิจกรรม
17 มี.ค. 21 - 21 มี.ค. 10
สร้างแอป AI และตัวแทน เข้าร่วมชุด meetup เพื่อสร้างโซลูชัน AI ที่ปรับขนาดได้ตามกรณีการใช้งานจริงกับนักพัฒนาและผู้เชี่ยวชาญร่วมกัน
ลงทะเบียนตอนนี้เบราว์เซอร์นี้ไม่ได้รับการสนับสนุนอีกต่อไป
อัปเกรดเป็น Microsoft Edge เพื่อใช้ประโยชน์จากคุณลักษณะล่าสุด เช่น การอัปเดตความปลอดภัยและการสนับสนุนด้านเทคนิค
The Orleans runtime provides two mechanisms, called timers and reminders, that enable the developer to specify periodic behavior for grains.
Timers are used to create periodic grain behavior that isn't required to span multiple activations (instantiations of the grain). A timer is identical to the standard .NET System.Threading.Timer class. In addition, timers are subject to single-threaded execution guarantees within the grain activation that they operate on.
Each activation may have zero or more timers associated with it. The runtime executes each timer routine within the runtime context of the activation that it's associated with.
To start a timer, use the RegisterGrainTimer
method, which returns an IGrainTimer reference:
protected IGrainTimer RegisterGrainTimer<TState>(
Func<TState, CancellationToken, Task> callback, // function invoked when the timer ticks
TState state, // object to pass to callback
GrainTimerCreationOptions options) // timer creation options
To cancel the timer, you dispose of it.
A timer ceases to trigger if the grain is deactivated or when a fault occurs and its silo crashes.
Important considerations:
Grain.RegisterGrainTimer
is the amount of time that passes from the moment the Task
returned by callback
is resolved to the moment that the next invocation of callback
should occur. This not only makes it impossible for successive calls to callback
to overlap, but also makes it so that the length of time callback
takes to complete affects the frequency at which callback
is invoked. This is an important deviation from the semantics of System.Threading.Timer.callback
is delivered to an activation on a separate turn, and never runs concurrently with other turns on the same activation.Reminders are similar to timers, with a few important differences:
Reminders, being persistent, rely upon storage to function. You must specify which storage backing to use before the reminder subsystem functions. This is done by configuring one of the reminder providers via Use{X}ReminderService
extension methods, where X
is the name of the provider, for example, UseAzureTableReminderService.
Azure Table configuration:
// TODO replace with your connection string
const string connectionString = "YOUR_CONNECTION_STRING_HERE";
var silo = new HostBuilder()
.UseOrleans(builder =>
{
builder.UseAzureTableReminderService(connectionString)
})
.Build();
SQL:
const string connectionString = "YOUR_CONNECTION_STRING_HERE";
const string invariant = "YOUR_INVARIANT";
var silo = new HostBuilder()
.UseOrleans(builder =>
{
builder.UseAdoNetReminderService(options =>
{
options.ConnectionString = connectionString; // Redacted
options.Invariant = invariant;
});
})
.Build();
If you just want a placeholder implementation of reminders to work without needing to set up an Azure account or SQL database, then this gives you a development-only implementation of the reminder system:
var silo = new HostBuilder()
.UseOrleans(builder =>
{
builder.UseInMemoryReminderService();
})
.Build();
ข้อสำคัญ
If you have a heterogenous cluster, where the silos handle different grain types (implement different interfaces), every silo must add the configuration for Reminders, even if the silo itself doesn't handle any reminders.
A grain that uses reminders must implement the IRemindable.ReceiveReminder method.
Task IRemindable.ReceiveReminder(string reminderName, TickStatus status)
{
Console.WriteLine("Thanks for reminding me-- I almost forgot!");
return Task.CompletedTask;
}
To start a reminder, use the Grain.RegisterOrUpdateReminder method, which returns an IGrainReminder object:
protected Task<IGrainReminder> RegisterOrUpdateReminder(
string reminderName,
TimeSpan dueTime,
TimeSpan period)
reminderName
: is a string that must uniquely identify the reminder within the scope of the contextual grain.dueTime
: specifies a quantity of time to wait before issuing the first-timer tick.period
: specifies the period of the timer.Since reminders survive the lifetime of any single activation, they must be explicitly canceled (as opposed to being disposed). You cancel a reminder by calling Grain.UnregisterReminder:
protected Task UnregisterReminder(IGrainReminder reminder)
The reminder
is the handle object returned by Grain.RegisterOrUpdateReminder.
Instances of IGrainReminder
aren't guaranteed to be valid beyond the lifespan of an activation. If you wish to identify a reminder in a way that persists, use a string containing the reminder's name.
If you only have the reminder's name and need the corresponding instance of IGrainReminder
, call the Grain.GetReminder method:
protected Task<IGrainReminder> GetReminder(string reminderName)
We recommend that you use timers in the following circumstances:
We recommend that you use reminders in the following circumstances:
You might consider using a combination of reminders and timers to accomplish your goal. For example, if you need a timer with a small resolution that needs to survive across activations, you can use a reminder that runs every five minutes, whose purpose is to wake up a grain that restarts a local timer that may have been lost due to deactivation.
To register a timer or reminder with a POCO grain, you implement the IGrainBase interface and inject the ITimerRegistry or IReminderRegistry into the grain's constructor.
using Orleans.Timers;
namespace Timers;
public sealed class PingGrain : IGrainBase, IPingGrain, IDisposable
{
private const string ReminderName = "ExampleReminder";
private readonly IReminderRegistry _reminderRegistry;
private IGrainReminder? _reminder;
public IGrainContext GrainContext { get; }
public PingGrain(
ITimerRegistry timerRegistry,
IReminderRegistry reminderRegistry,
IGrainContext grainContext)
{
// Register timer
timerRegistry.RegisterGrainTimer(
grainContext,
callback: static async (state, cancellationToken) =>
{
// Omitted for brevity...
// Use state
await Task.CompletedTask;
},
state: this,
options: new GrainTimerCreationOptions
{
DueTime = TimeSpan.FromSeconds(3),
Period = TimeSpan.FromSeconds(10)
});
_reminderRegistry = reminderRegistry;
GrainContext = grainContext;
}
public async Task Ping()
{
_reminder = await _reminderRegistry.RegisterOrUpdateReminder(
callingGrainId: GrainContext.GrainId,
reminderName: ReminderName,
dueTime: TimeSpan.Zero,
period: TimeSpan.FromHours(1));
}
void IDisposable.Dispose()
{
if (_reminder is not null)
{
_reminderRegistry.UnregisterReminder(
GrainContext.GrainId, _reminder);
}
}
}
The preceding code:
IPingGrain
, and IDisposable.Ping
is called, registers a reminder that is invoked every hour, and starts immediately following registration.Dispose
method cancels the reminder if it's registered.คำติชม .NET
.NET เป็นโครงการโอเพนซอร์ส เลือกลิงก์เพื่อให้คำติชม:
กิจกรรม
17 มี.ค. 21 - 21 มี.ค. 10
สร้างแอป AI และตัวแทน เข้าร่วมชุด meetup เพื่อสร้างโซลูชัน AI ที่ปรับขนาดได้ตามกรณีการใช้งานจริงกับนักพัฒนาและผู้เชี่ยวชาญร่วมกัน
ลงทะเบียนตอนนี้การฝึกอบรม
โมดูล
สร้างแอป Orleans แรกของคุณด้วย ASP.NET Core 8.0 - Training
เรียนรู้วิธีการสร้างแอปแบบกระจายในระบบคลาวด์ด้วย Orleans