Dignus.Actor.Core
2.1.2
dotnet add package Dignus.Actor.Core --version 2.1.2
NuGet\Install-Package Dignus.Actor.Core -Version 2.1.2
<PackageReference Include="Dignus.Actor.Core" Version="2.1.2" />
<PackageVersion Include="Dignus.Actor.Core" Version="2.1.2" />
<PackageReference Include="Dignus.Actor.Core" />
paket add Dignus.Actor.Core --version 2.1.2
#r "nuget: Dignus.Actor.Core, 2.1.2"
#:package Dignus.Actor.Core@2.1.2
#addin nuget:?package=Dignus.Actor.Core&version=2.1.2
#tool nuget:?package=Dignus.Actor.Core&version=2.1.2
Dignus.Actor.Core
Core actor runtime and messaging primitives for Dignus.
Overview
Dignus.Actor.Core provides the fundamental runtime for actor-based execution.
It implements a message-driven concurrency model where actors process messages sequentially on dedicated dispatcher threads.
This package focuses purely on:
- execution
- messaging
- scheduling
Scope
Dignus.Actor.Core includes only the actor runtime.
Networking and server features are provided by:
Dignus.ActorServer
Design Goals
- Single-threaded logical execution per actor
- Message-driven concurrency model
- No shared mutable state between actors
- Deterministic scheduling via dispatcher
- Lightweight and high-performance runtime
- Request/response messaging through Ask
Core Components
ActorSystem
Responsible for:
- creating and registering actors
- routing messages to actor mailboxes
- assigning actors to dispatchers
- controlling actor lifecycle
ActorBase
Base class for all actors.
- processes incoming messages
- maintains actor-local state
- executes on a single dispatcher thread
- exposes
Selfas anIAskActorRef
IActorMessage
Marker interface for messages exchanged between actors.
- represents a message that can be sent between actors
- all actor communication is done through messages
- has no behavior
IActorRef
Reference to an actor.
- used to send messages
- hides the actual actor instance
- enables safe communication
IAskActorRef
Reference to an actor that supports request/response messaging.
- extends
IActorRef - sends Ask request messages
- waits for a response message
- intended for low-frequency request/response flows
Dispatcher
Execution unit of the actor system.
- owns a dedicated thread
- schedules actor execution
- ensures sequential processing per actor
- resumes async continuations on the same thread
Concurrency Model
- each actor processes messages sequentially
- no concurrent execution inside a single actor
- no shared state between actors
- communication only through messages
This keeps actor logic simple and predictable.
Creating and Registering Actors
Actors are created and registered through ActorSystem.
Create ActorSystem
var actorSystem = new ActorSystem();
By default, the number of dispatcher threads equals Environment.ProcessorCount.
Spawn Actor (Auto Dispatcher)
IAskActorRef actorRef = actorSystem.Spawn<SampleActor>();
This will:
- create the actor
- assign a unique actor id
- automatically select a dispatcher
- register the actor
- return an
IAskActorRef
Dispatcher selection is based on:
dispatcherIndex = actorId % dispatcherCount
Spawn Actor (Explicit Dispatcher)
IAskActorRef actorRef = actorSystem.SpawnOnDispatcher<SampleActor>(0);
Use this when the actor must run on a specific dispatcher.
Spawn with Factory
IAskActorRef actorRef = actorSystem.Spawn(() => new SampleActor());
IAskActorRef actorRef2 = actorSystem.SpawnOnDispatcher(
() => new SampleActor(),
0);
Alias Registration
IAskActorRef actorRef = actorSystem.Spawn<SampleActor>(alias: "sample");
Resolve later:
if (actorSystem.TryGetActorRef("sample", out var actorRef))
{
}
Mailbox Capacity
IAskActorRef actorRef = actorSystem.Spawn<SampleActor>(
alias: "sample",
mailboxCapacity: 2048);
Sending Messages
Actors communicate only through messages.
Post sends a message to an actor without waiting for a response.
The message is enqueued into the target actor mailbox and processed later by the actor dispatcher.
Use Post when the caller does not need a return value.
actorRef.Post(new PingMessage());
Messages must implement:
public readonly struct PingMessage : IActorMessage
{
}
Post is fire-and-forget.
The caller does not receive a result from the target actor, and the call only represents message delivery to the actor reference.
If the target actor needs to send another message later, it should do so explicitly through another actor reference.
Ask Request/Response
Ask is used when the caller needs a response from an actor.
Use Post for fire-and-forget messages when no response is needed.
Use Ask when the caller must wait for a response from the target actor.
CreateRoomResponse response = await actorRef.AskAsync<CreateRoomResponse>(
new CreateRoomRequest(),
3000);
Ask does not require request or response messages to expose a request id.
Messages only need to implement IActorMessage.
public sealed class CreateRoomRequest : IActorMessage
{
public long RoomNumber { get; set; }
}
public sealed class CreateRoomResponse : IActorMessage
{
public bool Ok { get; set; }
public long RoomNumber { get; set; }
}
When handling an Ask request, the receiving actor should send the response message back to sender.
sender.Post(new CreateRoomResponse()
{
Ok = true,
RoomNumber = request.RoomNumber
}, Self);
The Ask runtime internally tracks the request and completes the waiting task when the response message is posted to the Ask reply reference.
The response type must match the type requested by AskAsync<TResponse>.
Ask is intended for control-flow operations such as:
- room creation
- database queries
- server-side commands
- management requests
Do not use Ask for high-frequency game-loop messages.
Post vs Ask
Use Post when the caller only needs to send a message.
Use Ask when the caller needs to wait for a response.
Post
caller -> target actor mailbox
caller continues immediately
Ask
caller -> target actor mailbox
caller waits for response task
target actor -> sender.Post(response, Self)
In most actor flows, prefer Post.
Use Ask only when the response is required for the next control-flow step.
Actor Example
public readonly struct PingMessage : IActorMessage
{
}
public sealed class SampleActor : ActorBase
{
protected override ValueTask OnReceive(IActorMessage message, IActorRef sender)
{
if (message is PingMessage)
{
}
return ValueTask.CompletedTask;
}
}
Ask Example
public sealed class CreateRoomRequest : IActorMessage
{
public long RoomNumber { get; set; }
}
public sealed class CreateRoomResponse : IActorMessage
{
public bool Ok { get; set; }
public long RoomNumber { get; set; }
}
public sealed class RoomManagerActor : ActorBase
{
protected override ValueTask OnReceive(IActorMessage message, IActorRef sender)
{
if (message is CreateRoomRequest request)
{
sender.Post(new CreateRoomResponse()
{
Ok = true,
RoomNumber = request.RoomNumber
}, Self);
}
return ValueTask.CompletedTask;
}
}
CreateRoomResponse response = await roomManagerActorRef.AskAsync<CreateRoomResponse>(
new CreateRoomRequest()
{
RoomNumber = 1
},
3000);
Benchmark
Local in-process ping-pong benchmark.
Test environment:
CPU: Intel Core i5-12400F
RAM: 32 GB
OS: Windows x64
Benchmark conditions:
Actor Pair Count: 348
Actual Actor Count: 696
Pipeline Size Per Pair: 1,000
Benchmark Duration: 10 seconds
Counter: per-actor local counter, summed after completion
Best observed result:
Processed Messages: 2,907,908,768
Elapsed: 10.475 sec
Throughput: 277,599,493 msg/s
Representative result:
Throughput: around 250M ~ 270M msg/s
Notes:
- This benchmark measures local actor message throughput only.
- It does not include network, serialization, database access, logging, or game logic.
- Per-message global synchronization was intentionally avoided.
- Results may vary depending on CPU scheduling, background processes, power mode, GC timing, and runtime warm-up.
Lifecycle
- actor is created via
Spawn - messages are queued in mailbox
- dispatcher executes messages sequentially
- actor is removed when killed
Summary
ActorSystem→ creates and manages actorsActorBase→ implements actor logicIActorRef→ sends messagesIAskActorRef→ sends request/response messagesDispatcher→ executes actorsIActorMessage→ defines actor messages
When to Use
Use Dignus.Actor.Core when you need:
- actor-based concurrency
- deterministic execution
- message-driven architecture
- isolation between components
- request/response messaging between actors
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Dignus (>= 1.1.4)
- Dignus.Actor.Abstractions (>= 1.0.1)
-
net10.0
- Dignus (>= 1.1.4)
- Dignus.Actor.Abstractions (>= 1.0.1)
-
net8.0
- Dignus (>= 1.1.4)
- Dignus.Actor.Abstractions (>= 1.0.1)
-
net9.0
- Dignus (>= 1.1.4)
- Dignus.Actor.Abstractions (>= 1.0.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Dignus.Actor.Core:
| Package | Downloads |
|---|---|
|
Dignus.ActorServer
Actor-based server framework built on top of Dignus and Dignus.Sockets for scalable message-driven network servers. |
GitHub repositories
This package is not used by any popular GitHub repositories.