Skip to content

Commit 1ce75d4

Browse files
authored
Merge pull request #3 from dombrovsky/f/documentation
documentation 1st draft
2 parents a36ea07 + 5aede12 commit 1ce75d4

13 files changed

Lines changed: 893 additions & 5 deletions

README.md

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,60 @@
1-
# TaskFlow
1+
# TaskFlow
2+
3+
**TaskFlow** is a robust, high-performance, extensible, and thread-safe library for orchestrating and controlling the execution of asynchronous tasks in .NET. It provides advanced patterns for sequential task execution, resource management, and cancellation, making it ideal for scenarios where you need more than just `SemaphoreSlim` or basic Task chaining.
4+
5+
[![NuGet](https://img.shields.io/nuget/v/TaskFlow.svg)](https://www.nuget.org/packages/TaskFlow/)
6+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7+
8+
---
9+
10+
## Key Features
11+
12+
- **Sequential Task Execution:** Guarantee that tasks are executed in the order they are enqueued, with no concurrency unless explicitly configured.
13+
- **Thread Affinity:** Run tasks on a dedicated thread, the current thread, or the thread pool, with full control over execution context.
14+
- **Robust Disposal:** Dispose/DisposeAsync will only complete after all enqueued tasks have finished, ensuring clean shutdowns. This makes it ideal for managing fire-and-forget tasks by binding their lifetime to a specific scope.
15+
- **Cancellation Support:** All enqueued task functions are executed, even if canceled before execution, ensuring predictable execution order.
16+
- **SynchronizationContext Awareness:** Async/await inside enqueued delegates will execute continuations on the same `TaskFlow` if a `SynchronizationContext` is captured.
17+
- **Extensibility:** Extend `TaskFlowBase` to create custom task flow implementations or use extension methods and wrappers to enhance functionality, such as throttling, error handling, or scoped cancellation.
18+
- **Clean Task Pipeline Definition:** Define task pipelines separately from execution logic using extension methods from `System.Threading.Tasks.Flow.Extensions`, enabling better segregation of responsibilities and cleaner code.
19+
- **Dependency Injection Integration:** Extensions for `Microsoft.Extensions.DependencyInjection` for easy registration and scoping.
20+
21+
---
22+
23+
## When Should You Use TaskFlow?
24+
25+
TaskFlow is ideal for scenarios where you need:
26+
27+
- **Serialized access to a resource** (e.g., database, file, hardware) from multiple async operations.
28+
- **Order-preserving task execution** (e.g., message processing, event handling).
29+
- **Thread affinity** (e.g., UI thread, dedicated worker thread).
30+
- **Graceful shutdown** with guaranteed completion of all in-flight work.
31+
- **Advanced error handling and cancellation patterns.**
32+
- **Fire-and-forget task lifetime management:** Bind fire-and-forget operations to a scope by disposing the `TaskFlow` instance, ensuring proper cleanup and resource management.
33+
- **Segregation of responsibilities:** Use extension methods to define task pipelines separately from execution logic, improving maintainability and readability.
34+
35+
---
36+
37+
## Getting Started
38+
39+
### Installation
40+
41+
Add the core package:
42+
`dotnet add package TaskFlow`
43+
44+
For dependency injection support:
45+
`dotnet add package TaskFlow.Microsoft.Extensions.DependencyInjection`
46+
### Basic Usage
47+
```csharp
48+
using var taskFlow = new TaskFlow();
49+
50+
// Enqueue tasks for sequential execution
51+
var task1 = taskFlow.Enqueue(() => Console.WriteLine("Task 1"));
52+
var task2 = taskFlow.Enqueue(async () => await Task.Delay(100));
53+
```
54+
---
55+
56+
## Extensions
57+
58+
## License
59+
60+
This library is licensed under the [MIT License](LICENSE).

TaskFlow.Extensions.Microsoft.DependencyInjection.Tests/CustomTaskFlowServiceCollectionExtensionsFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace TaskFlow.Extensions.Microsoft.DependencyInjection.Tests
66
using System.Threading.Tasks.Flow;
77

88
[TestFixture]
9-
public sealed class CustomTaskFlowServiceCollectionExtensionsFixture
9+
internal sealed class CustomTaskFlowServiceCollectionExtensionsFixture
1010
{
1111
[Test]
1212
public void AddTaskFlow_ShouldRegisterTaskFlowInfoAndTaskScheduler()

TaskFlow.Extensions.Microsoft.DependencyInjection.Tests/DefaultTaskFlowServiceCollectionExtensionsFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace TaskFlow.Extensions.Microsoft.DependencyInjection.Tests
55
using System.Threading.Tasks.Flow;
66

77
[TestFixture]
8-
public sealed class DefaultTaskFlowServiceCollectionExtensionsFixture
8+
internal sealed class DefaultTaskFlowServiceCollectionExtensionsFixture
99
{
1010
[Test]
1111
public void AddTaskFlow_ShouldRegisterTaskFlowInfoAndTaskScheduler()

TaskFlow/CurrentThreadTaskFlow.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,99 @@
11
namespace System.Threading.Tasks.Flow
22
{
3+
/// <summary>
4+
/// A task flow implementation that executes tasks on the thread that calls the <see cref="Run"/> method.
5+
/// </summary>
6+
/// <remarks>
7+
/// <para>
8+
/// The <see cref="CurrentThreadTaskFlow"/> class provides a task scheduling mechanism that
9+
/// executes tasks on a specific thread provided by the caller. Unlike <see cref="DedicatedThreadTaskFlow"/>,
10+
/// which creates its own thread, this class allows you to use an existing thread for task execution.
11+
/// </para>
12+
/// <para>
13+
/// This implementation is useful when you want to execute tasks on a specific thread, such as:
14+
/// </para>
15+
/// <list type="bullet">
16+
/// <item>A UI thread in a desktop application</item>
17+
/// <item>A worker thread that you manage externally</item>
18+
/// <item>A thread with specific properties or priority settings</item>
19+
/// </list>
20+
/// <para>
21+
/// Note that the <see cref="Run"/> method must be called to start the task flow, and it
22+
/// will block the calling thread until the task flow is disposed.
23+
/// </para>
24+
/// <example>
25+
/// Basic usage with a background thread:
26+
/// <code>
27+
/// var taskFlow = new CurrentThreadTaskFlow();
28+
///
29+
/// // Start the task flow on a background thread
30+
/// var thread = new Thread(() => taskFlow.Run()) { IsBackground = true };
31+
/// thread.Start();
32+
///
33+
/// // Enqueue tasks for execution on the background thread
34+
/// var task1 = taskFlow.Enqueue(() => Console.WriteLine("Task 1"));
35+
/// var task2 = taskFlow.Enqueue(() => Console.WriteLine("Task 2"));
36+
///
37+
/// // Wait for tasks to complete and dispose the task flow
38+
/// await Task.WhenAll(task1, task2);
39+
/// await taskFlow.DisposeAsync();
40+
/// </code>
41+
/// </example>
42+
/// </remarks>
343
public sealed class CurrentThreadTaskFlow : ThreadTaskFlow
444
{
545
private int _managedThreadId;
646

47+
/// <summary>
48+
/// Initializes a new instance of the <see cref="CurrentThreadTaskFlow"/> class with default options.
49+
/// </summary>
50+
/// <remarks>
51+
/// This constructor uses the default options from <see cref="TaskFlowOptions.Default"/>.
52+
/// The task flow will not start processing tasks until the <see cref="Run"/> method is called.
53+
/// </remarks>
754
public CurrentThreadTaskFlow()
855
: this(TaskFlowOptions.Default)
956
{
1057
}
1158

59+
/// <summary>
60+
/// Initializes a new instance of the <see cref="CurrentThreadTaskFlow"/> class with the specified options.
61+
/// </summary>
62+
/// <param name="options">The options that configure the behavior of this task flow.</param>
63+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="options"/> is null.</exception>
64+
/// <remarks>
65+
/// The task flow will not start processing tasks until the <see cref="Run"/> method is called.
66+
/// </remarks>
1267
public CurrentThreadTaskFlow(TaskFlowOptions options)
1368
: base(options)
1469
{
1570
}
1671

72+
/// <summary>
73+
/// Gets the managed thread ID of the thread that is executing tasks in this task flow.
74+
/// </summary>
75+
/// <remarks>
76+
/// This property returns the thread ID of the thread that called the <see cref="Run"/> method.
77+
/// If the <see cref="Run"/> method has not been called yet, the thread ID is not defined.
78+
/// </remarks>
1779
public override int ThreadId => _managedThreadId;
1880

81+
/// <summary>
82+
/// Starts the task flow execution on the current thread and blocks until the task flow is disposed.
83+
/// </summary>
84+
/// <remarks>
85+
/// <para>
86+
/// This method must be called to start the task flow and begin processing tasks.
87+
/// It will block the calling thread until the task flow is disposed.
88+
/// </para>
89+
/// <para>
90+
/// Tasks enqueued before calling this method will be processed once it is called.
91+
/// Tasks enqueued after calling this method will be processed as they are received.
92+
/// </para>
93+
/// <para>
94+
/// To stop the execution, dispose the task flow from another thread or by using a cancellation token.
95+
/// </para>
96+
/// </remarks>
1997
public void Run()
2098
{
2199
Starting();

TaskFlow/DedicatedThreadTaskFlow.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,76 @@
11
namespace System.Threading.Tasks.Flow
22
{
3+
/// <summary>
4+
/// A task flow implementation that executes tasks on a dedicated background thread.
5+
/// </summary>
6+
/// <remarks>
7+
/// <para>
8+
/// The <see cref="DedicatedThreadTaskFlow"/> class provides a task scheduling mechanism that
9+
/// executes tasks on a dedicated background thread created specifically for this task flow.
10+
/// The thread is automatically started during construction and continues running until the task flow is disposed.
11+
/// </para>
12+
/// <para>
13+
/// This implementation is useful when you want to:
14+
/// </para>
15+
/// <list type="bullet">
16+
/// <item>Execute tasks in a background thread that doesn't block the main application thread</item>
17+
/// <item>Process tasks sequentially in a dedicated thread</item>
18+
/// <item>Isolate task execution from other parts of the application</item>
19+
/// </list>
20+
/// <para>
21+
/// The dedicated thread is created as a background thread, which means it will not prevent
22+
/// the application from exiting if all foreground threads have terminated.
23+
/// </para>
24+
/// <example>
25+
/// Basic usage:
26+
/// <code>
27+
/// // Create a task flow with a dedicated thread named "MyBackgroundThread"
28+
/// using var taskFlow = new DedicatedThreadTaskFlow("MyBackgroundThread");
29+
///
30+
/// // Enqueue tasks for execution on the dedicated thread
31+
/// var task1 = taskFlow.Enqueue(() => Console.WriteLine("Task 1"));
32+
/// var task2 = taskFlow.Enqueue(() => Console.WriteLine("Task 2"));
33+
///
34+
/// // Wait for tasks to complete
35+
/// await Task.WhenAll(task1, task2);
36+
/// </code>
37+
/// </example>
38+
/// </remarks>
339
public sealed class DedicatedThreadTaskFlow : ThreadTaskFlow
440
{
541
private readonly Thread _thread;
642

43+
/// <summary>
44+
/// Initializes a new instance of the <see cref="DedicatedThreadTaskFlow"/> class with default options and an optional name.
45+
/// </summary>
46+
/// <param name="name">Optional name for the dedicated thread. If null or empty, uses the class name.</param>
47+
/// <remarks>
48+
/// <para>
49+
/// This constructor uses the default options from <see cref="TaskFlowOptions.Default"/>.
50+
/// </para>
51+
/// <para>
52+
/// The task flow immediately creates and starts a dedicated background thread for processing tasks.
53+
/// </para>
54+
/// </remarks>
755
public DedicatedThreadTaskFlow(string? name = default)
856
: this(TaskFlowOptions.Default, name)
957
{
1058
}
1159

60+
/// <summary>
61+
/// Initializes a new instance of the <see cref="DedicatedThreadTaskFlow"/> class with the specified options and an optional name.
62+
/// </summary>
63+
/// <param name="options">The options that configure the behavior of this task flow.</param>
64+
/// <param name="name">Optional name for the dedicated thread. If null or empty, uses the class name.</param>
65+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="options"/> is null.</exception>
66+
/// <remarks>
67+
/// <para>
68+
/// The task flow immediately creates and starts a dedicated background thread for processing tasks.
69+
/// </para>
70+
/// <para>
71+
/// The thread name is useful for debugging and thread identification in thread dumps or profiling tools.
72+
/// </para>
73+
/// </remarks>
1274
public DedicatedThreadTaskFlow(TaskFlowOptions options, string? name = default)
1375
: base(options)
1476
{
@@ -22,6 +84,12 @@ public DedicatedThreadTaskFlow(TaskFlowOptions options, string? name = default)
2284
_thread.Start(null);
2385
}
2486

87+
/// <summary>
88+
/// Gets the managed thread ID of the dedicated thread that is executing tasks in this task flow.
89+
/// </summary>
90+
/// <remarks>
91+
/// This property returns the thread ID of the dedicated thread created for this task flow.
92+
/// </remarks>
2593
public override int ThreadId => _thread.ManagedThreadId;
2694
}
2795
}

TaskFlow/ITaskFlow.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,45 @@
11
namespace System.Threading.Tasks.Flow
22
{
3+
/// <summary>
4+
/// Defines a unified interface for task flow execution that combines scheduling, information, and disposal capabilities.
5+
/// </summary>
6+
/// <remarks>
7+
/// <para>
8+
/// The <see cref="ITaskFlow"/> interface combines multiple interfaces to provide a complete API for task management:
9+
/// </para>
10+
/// <list type="bullet">
11+
/// <item><see cref="ITaskScheduler"/> - For enqueueing tasks for execution</item>
12+
/// <item><see cref="ITaskFlowInfo"/> - For accessing information about the task flow</item>
13+
/// <item><see cref="IAsyncDisposable"/> - For asynchronous cleanup of resources</item>
14+
/// <item><see cref="IDisposable"/> - For synchronous cleanup of resources</item>
15+
/// </list>
16+
/// <para>
17+
/// Implementations of this interface are responsible for:
18+
/// </para>
19+
/// <list type="bullet">
20+
/// <item>Managing the execution of tasks in a controlled manner</item>
21+
/// <item>Ensuring proper task cancellation during disposal</item>
22+
/// <item>Providing configuration options through the <see cref="ITaskFlowInfo.Options"/> property</item>
23+
/// <item>Supporting both synchronous and asynchronous disposal patterns</item>
24+
/// </list>
25+
/// </remarks>
326
public interface ITaskFlow : ITaskScheduler, ITaskFlowInfo, IAsyncDisposable, IDisposable
427
{
28+
/// <summary>
29+
/// Synchronously disposes the task flow with a specified timeout.
30+
/// </summary>
31+
/// <param name="timeout">The maximum time to wait for task completion.</param>
32+
/// <returns><c>true</c> if all tasks completed within the specified timeout; otherwise, <c>false</c>.</returns>
33+
/// <remarks>
34+
/// <para>
35+
/// This method attempts to dispose of the task flow asynchronously but with a time limit.
36+
/// If the specified timeout is reached before all tasks complete, the method returns <c>false</c>,
37+
/// but resources are still properly disposed.
38+
/// </para>
39+
/// <para>
40+
/// If tasks don't respond to cancellation, they may continue running after this method returns.
41+
/// </para>
42+
/// </remarks>
543
bool Dispose(TimeSpan timeout);
644
}
745
}

TaskFlow/ITaskFlowInfo.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,29 @@
11
namespace System.Threading.Tasks.Flow
22
{
3+
/// <summary>
4+
/// Defines a contract for accessing information about a task flow's configuration.
5+
/// </summary>
6+
/// <remarks>
7+
/// <para>
8+
/// The <see cref="ITaskFlowInfo"/> interface provides a way to access configuration
9+
/// information about a task flow without exposing the ability to schedule tasks or
10+
/// manage the task flow's lifecycle.
11+
/// </para>
12+
/// <para>
13+
/// This interface is useful for components that need to read task flow configuration
14+
/// but should not have the ability to enqueue tasks or dispose the task flow.
15+
/// </para>
16+
/// </remarks>
317
public interface ITaskFlowInfo
418
{
19+
/// <summary>
20+
/// Gets the options that configure the behavior of the task flow.
21+
/// </summary>
22+
/// <remarks>
23+
/// The options object contains configuration settings that affect the behavior
24+
/// of the task flow, such as the task scheduler to use and timeout settings
25+
/// for synchronous disposal operations.
26+
/// </remarks>
527
TaskFlowOptions Options { get; }
628
}
729
}

0 commit comments

Comments
 (0)