{"id":25236937,"url":"https://github.com/styropyr0/coroutines","last_synced_at":"2025-10-26T12:30:19.024Z","repository":{"id":273584613,"uuid":"920159170","full_name":"styropyr0/Coroutines","owner":"styropyr0","description":"This library provides a simple and efficient way to manage asynchronous code in .NET applications, inspired by Kotlin's coroutines. It supports custom dispatchers for flexible threading, and integrates seamlessly with existing Task-based code.","archived":false,"fork":false,"pushed_at":"2025-02-11T13:08:09.000Z","size":89,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-11T14:24:18.732Z","etag":null,"topics":["coroutines","csharp","csharp-core","csharp-library","dotnet","dotnet-core","kotlin","nuget-package","nuget-publisher","visual-studio","windows-11","windows-forms","wpf-application"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/styropyr0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-21T17:02:42.000Z","updated_at":"2025-02-11T13:08:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"2a8bd3fa-af77-40f6-97a5-d9227010ce02","html_url":"https://github.com/styropyr0/Coroutines","commit_stats":null,"previous_names":["styropyr0/coroutines"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styropyr0%2FCoroutines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styropyr0%2FCoroutines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styropyr0%2FCoroutines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/styropyr0%2FCoroutines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/styropyr0","download_url":"https://codeload.github.com/styropyr0/Coroutines/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238320065,"owners_count":19452466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coroutines","csharp","csharp-core","csharp-library","dotnet","dotnet-core","kotlin","nuget-package","nuget-publisher","visual-studio","windows-11","windows-forms","wpf-application"],"created_at":"2025-02-11T15:32:50.654Z","updated_at":"2025-10-26T12:30:18.712Z","avatar_url":"https://github.com/styropyr0.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Coroutines For CSharp - Detailed Documentation\n\n## Overview\n\nThis coroutine library offers an intuitive and flexible approach to asynchronous programming in C#, inspired by Kotlin's coroutine system. It simplifies concurrency by abstracting away the complexity of managing threads and execution contexts. This library provides a powerful model for suspending, resuming, and managing coroutines while ensuring clean and maintainable code. With advanced dispatchers, coroutine scopes, timeouts, and more, it is a comprehensive solution for handling asynchronous workflows in your C# applications.\n\n---\n\n## Features\n\n- **Dispatcher Abstraction**: Choose specific execution contexts, such as `DefaultContext`, `IOContext`, `MainContext`, and `UnconfinedContext`.\n- **Coroutine Scopes**: Manage the lifecycle of coroutines with `CoroutineScope` and `CoroutineScopeWithCancellation`.\n- **Global Coroutines**: Use `GlobalScope` for long-lived coroutines that are managed application-wide.\n- **Timeout Management**: Control execution time of coroutines with `CoroutineTimeout`.\n- **Parallel Execution**: Launch multiple coroutines concurrently with `CoroutineBuilder`.\n- **Suspension Functions**: Utilize cooperative multitasking with `Suspend` functions to pause execution and resume later.\n- **Exception Handling**: Robust handling of exceptions within coroutines (to be covered later).\n\n---\n\n## Installation\n\n### Prerequisites\n- .NET Core 3.1 or later\n- .NET Framework 4.7.2 or later\n\n### Adding the Library to Your Project\n\n1. Clone or download the repository:\n   ```bash\n   git clone https://github.com/styropyr0/Coroutines\n   ```\n2. Add the source files directly to your project, or compile the library into a `.dll` and reference it in your project.\n\nAlternatively, if you prefer to install via .NET CLI or Package Manager:\n```bash\ndotnet add package CoroutinesForCS --version \u003cversion\u003e\n```\n\n```bash\nNuGet\\Install-Package CoroutinesForCS -Version \u003cversion\u003e\n```\n---\n\n## Library Components\n\n## Core classes and methods\n\n### 1. Dispatchers\n\nDispatchers are central to the coroutine library as they define the execution context for coroutines. Each dispatcher determines where and how coroutines are executed, whether on the default thread pool, a dedicated I/O thread, the main thread, or on any available thread.\n\n#### **`DefaultContext`**\n- This dispatcher uses the default thread pool to execute tasks.\n- Suitable for CPU-bound tasks and general-purpose work.\n- **Methods**:\n  - `Task ExecuteAsync(Func\u003cTask\u003e task, CancellationToken cancellationToken)`: Executes a coroutine asynchronously.\n  - `Task\u003cT\u003e ExecuteAsync\u003cT\u003e(Func\u003cTask\u003cT\u003e\u003e task, CancellationToken cancellationToken)`: Executes a coroutine asynchronously with a result.\n- **Returns**: A new instance of `DefaultContext`.\n\n#### **`IOContext`**\n- Designed for I/O-bound operations (such as file access, network requests, etc.).\n- Executes tasks on a dedicated thread pool to prevent blocking the main thread.\n- **Methods**:\n  - `Task ExecuteAsync(Func\u003cTask\u003e task, CancellationToken cancellationToken)`: Executes an I/O-bound task asynchronously.\n  - `Task\u003cT\u003e ExecuteAsync\u003cT\u003e(Func\u003cTask\u003cT\u003e\u003e task, CancellationToken cancellationToken)`: Executes an I/O-bound task asynchronously with a result.\n- **Returns**: A new instance of `IOContext`.\n\n#### **`MainContext`**\n- Executes coroutines on the main thread using a `SynchronizationContext`. This is useful for UI-related tasks that need to interact with the UI thread.\n- **Methods**:\n  - `Task ExecuteAsync(Func\u003cTask\u003e task, CancellationToken cancellationToken)`: Executes a coroutine on the main thread asynchronously.\n  - `Task\u003cT\u003e ExecuteAsync\u003cT\u003e(Func\u003cTask\u003cT\u003e\u003e task, CancellationToken cancellationToken)`: Executes a coroutine on the main thread asynchronously with a result.\n- **Returns**: A new instance of `MainContext`.\n\n#### **`UnconfinedContext`**\n- Executes coroutines without binding to a specific thread. The coroutine will be resumed on whichever thread is available.\n- This context is ideal for operations that do not require a fixed execution thread.\n- **Methods**:\n  - `Task ExecuteAsync(Func\u003cTask\u003e task, CancellationToken cancellationToken)`: Executes a coroutine without a fixed execution thread.\n  - `Task\u003cT\u003e ExecuteAsync\u003cT\u003e(Func\u003cTask\u003cT\u003e\u003e task, CancellationToken cancellationToken)`: Executes a coroutine without a fixed execution thread, returning a result.\n- **Returns**: A new instance of `UnconfinedContext`.\n\n---\n\n### Example of Dispatcher Usage:\n\n```csharp\n// Creating and using Dispatchers\n\n// DefaultContext\nvar defaultDispatcher = Dispatcher.Default;\nawait defaultDispatcher.ExecuteAsync(async () =\u003e\n{\n    Console.WriteLine(\"Running on the default context\");\n});\n\n// IOContext\nvar ioDispatcher = Dispatcher.IO;\nawait ioDispatcher.ExecuteAsync(async () =\u003e\n{\n    Console.WriteLine(\"Running I/O bound task\");\n});\n\n// MainContext\nvar mainDispatcher = Dispatcher.Main;\nawait mainDispatcher.ExecuteAsync(async () =\u003e\n{\n    Console.WriteLine(\"Running on the main thread for UI operations\");\n});\n\n// UnconfinedContext\nvar unconfinedDispatcher = Dispatcher.Unconfined;\nawait unconfinedDispatcher.ExecuteAsync(async () =\u003e\n{\n    Console.WriteLine(\"Running in an unconfined context\");\n});\n```\n\n\n### 2. CoroutineScope\n\nThe `CoroutineScope` class is designed to manage and coordinate the execution of coroutines within a specific context or dispatcher. It allows you to launch multiple coroutines, handle cancellations, and wait for their completion in an organized manner.\n\n#### **Key Features:**\n- **Manage Coroutine Execution**: Provides methods to launch coroutines that can run in parallel or sequentially.\n- **Scope-based Cancellation**: Supports cancellation of all coroutines within the scope.\n- **Task Coordination**: Wait for all launched tasks to complete or cancel them when needed.\n- **Combine Coroutines**: Allows combining multiple coroutines into one operation, waiting for all or the first one to complete.\n\n#### **Constructor:**\n- `CoroutineScope(Dispatcher context)`  \n  Initializes a new instance of the `CoroutineScope` class with a specified dispatcher. The dispatcher defines where the coroutines will run (e.g., on the main thread, I/O thread, etc.).\n\n#### **Methods:**\n\n- **Launch (Action)**  \n  Launches a coroutine that takes no parameters and returns no value.  \n  ```csharp\n  public async Task Launch(Action coroutine, Dispatcher dispatcher = null)\n  ```\n\n- **Launch (Func\u003cT\u003e)**  \n  Launches a coroutine that takes a value and returns that value.  \n  ```csharp\n  public async Task Launch\u003cT\u003e(Func\u003cT\u003e coroutine, Dispatcher dispatcher = null)\n  ```\n\n- **Launch (Func\u003cTask\u003e)**  \n  Launches a coroutine that returns a `Task` and waits for its completion.  \n  ```csharp\n  public async Task Launch(Func\u003cTask\u003e coroutine, Dispatcher dispatcher = null)\n  ```\n\n- **Combine (Action)**  \n  Combines multiple coroutines that take no parameters and run them in parallel.  \n  ```csharp\n  public async Task Combine(IEnumerable\u003cAction\u003e coroutines, Dispatcher dispatcher = null)\n  ```\n\n- **Combine (Func\u003cT\u003e)**  \n  Combines multiple coroutines that take a value and run them in parallel.  \n  ```csharp\n  public async Task Combine\u003cT\u003e(IEnumerable\u003cFunc\u003cT\u003e\u003e coroutines, Dispatcher dispatcher = null)\n  ```\n\n- **Combine (Func\u003cTask\u003e)**  \n  Combines multiple coroutines that return a `Task` and runs them in parallel.  \n  ```csharp\n  public async Task Combine(IEnumerable\u003cFunc\u003cTask\u003e\u003e coroutines, Dispatcher dispatcher = null)\n  ```\n\n- **CombineFirst (Action)**  \n  Combines multiple coroutines and executes the first one to complete.  \n  ```csharp\n  public async Task CombineFirst(IEnumerable\u003cAction\u003e coroutines, Dispatcher dispatcher = null)\n  ```\n\n- **CombineFirst (Func\u003cTask\u003e)**  \n  Combines multiple coroutines that return a `Task` and executes the first one to complete.  \n  ```csharp\n  public async Task CombineFirst(IEnumerable\u003cFunc\u003cTask\u003e\u003e coroutines, Dispatcher dispatcher = null)\n  ```\n\n- **WaitAllAsync**  \n  Waits for all coroutines to complete in the current scope.  \n  ```csharp\n  public async Task WaitAllAsync()\n  ```\n\n- **Cancel**  \n  Cancels all coroutines in the current scope.  \n  ```csharp\n  public void Cancel()\n  ```\n\n- **DisposeAsync**  \n  Disposes of the `CoroutineScope`, cancelling any ongoing coroutines and waiting for them to finish.  \n  ```csharp\n  public async ValueTask DisposeAsync()\n  ```\n\n- **GetTasks**  \n  Gets the collection of tasks that are still running and not cancelled.  \n  ```csharp\n  public IEnumerable\u003cTask\u003e GetTasks(CancellationToken cancellationToken)\n  ```\n\n---\n\n#### Example Usage of `CoroutineScope`:\n\n```csharp\n// Initialize the CoroutineScope with a specific dispatcher\nvar scope = new CoroutineScope(Dispatcher.IO);\n\n// Launch a coroutine that takes no parameters\nawait scope.Launch(() =\u003e\n{\n    Console.WriteLine(\"Running a simple coroutine.\");\n});\n\n// Launch a coroutine that returns a result\nawait scope.Launch(() =\u003e\n{\n    return 42; // Example returning a result\n});\n\n// Combine multiple coroutines to run in parallel\nawait scope.Combine(new List\u003cAction\u003e\n{\n    () =\u003e Console.WriteLine(\"First parallel task\"),\n    () =\u003e Console.WriteLine(\"Second parallel task\")\n});\n\n// Wait for all tasks in the scope to complete\nawait scope.WaitAllAsync();\n\n// Cancel all running coroutines\nscope.Cancel();\n\n// Dispose of the scope when done\nawait scope.DisposeAsync();\n```\n\n\n### 3. GlobalScope\n\n`GlobalScope` provides global access to coroutine scopes and utilities for launching, combining, and managing coroutines. It acts as a container for coroutines, handling their execution across different dispatcher contexts. This section explains how to use `GlobalScope` to manage coroutine tasks globally.\n\n### Methods:\n\n#### 3.1 Launching Coroutines\n\n- **Launch No Parameters**:\n  ```csharp\n  public static async Task Launch(Action coroutine, Dispatcher dispatcher = null, CancellationToken cancellationToken = default)\n  ```\n  Launches a coroutine with no parameters (an `Action`) in the given `dispatcher` context. If no dispatcher is provided, the default dispatcher is used.\n\n- **Launch With Return Value**:\n  ```csharp\n  public static async Task Launch\u003cT\u003e(Func\u003cT\u003e coroutine, Dispatcher dispatcher = null, CancellationToken cancellationToken = default)\n  ```\n  Launches a coroutine that returns a value of type `T`.\n\n- **Launch Task Coroutine**:\n  ```csharp\n  public static async Task Launch(Func\u003cTask\u003e coroutine, Dispatcher dispatcher = null, CancellationToken cancellationToken = default)\n  ```\n  Launches a coroutine that returns a `Task` and waits for its completion.\n\n#### 3.2 Combining Coroutines\n\n- **Combine No Parameters**:\n  ```csharp\n  public static async Task Combine(IEnumerable\u003cAction\u003e coroutines, Dispatcher dispatcher = null, CancellationToken cancellationToken = default)\n  ```\n  Combines multiple `Action` coroutines and runs them in parallel.\n\n- **Combine With Return Values**:\n  ```csharp\n  public static async Task Combine\u003cT\u003e(IEnumerable\u003cFunc\u003cT\u003e\u003e coroutines, Dispatcher dispatcher = null, CancellationToken cancellationToken = default)\n  ```\n  Combines multiple coroutines that return values of type `T` and runs them in parallel.\n\n- **Combine Task Coroutines**:\n  ```csharp\n  public static async Task Combine(IEnumerable\u003cFunc\u003cTask\u003e\u003e coroutines, Dispatcher dispatcher = null, CancellationToken cancellationToken = default)\n  ```\n  Combines multiple `Task`-returning coroutines and runs them in parallel.\n\n- **Combine First to Complete**:\n  ```csharp\n  public static async Task CombineFirst(IEnumerable\u003cAction\u003e coroutines, Dispatcher dispatcher = null, CancellationToken cancellationToken = default)\n  ```\n  Combines multiple `Action` coroutines and executes the first one to complete.\n\n- **Combine Task First to Complete**:\n  ```csharp\n  public static async Task CombineFirst(IEnumerable\u003cFunc\u003cTask\u003e\u003e coroutines, Dispatcher dispatcher = null, CancellationToken cancellationToken = default)\n  ```\n  Combines multiple `Task`-returning coroutines and executes the first one to complete.\n\n#### 3.3 Managing Coroutine Execution\n\n- **Wait for All Coroutines**:\n  ```csharp\n  public static async Task WaitAllAsync(CancellationToken cancellationToken = default)\n  ```\n  Waits for all coroutines in the global scope to complete.\n\n- **Cancel All Coroutines**:\n  ```csharp\n  public static void CancelAll()\n  ```\n  Cancels all running coroutines in the global scope.\n\n- **Dispose All Scopes**:\n  ```csharp\n  public static async Task DisposeAllAsync()\n  ```\n  Disposes of all coroutine scopes in the global scope asynchronously.\n\n\n### 4. CoroutineBuilder\n\n`CoroutineBuilder` provides utility methods for launching and managing coroutines with dispatchers. It simplifies launching coroutine blocks and executing multiple coroutines in parallel, handling their execution on specific dispatchers. This section explains how to use `CoroutineBuilder` for coroutine management.\n\n### Methods:\n\n#### 4.1 Launch a Coroutine Block\n\n```csharp\npublic static async Task Launch(Func\u003cTask\u003e block, Dispatcher dispatcher = null)\n```\nLaunches a single coroutine block using the specified `dispatcher`. If no dispatcher is provided, the default dispatcher is used.\n\n- **Parameters**:\n  - `block`: The coroutine block to execute.\n  - `dispatcher`: The dispatcher context to execute the coroutine block. If `null`, the default dispatcher is used.\n  \n- **Returns**:\n  - A `Task` representing the asynchronous operation.\n\n#### 4.2 Launch Multiple Coroutines in Parallel (Asynchronous)\n\n```csharp\npublic static async Task LaunchAll(IEnumerable\u003cFunc\u003cTask\u003e\u003e blocks, Dispatcher dispatcher = null)\n```\nExecutes multiple asynchronous coroutines in parallel and waits for all to complete.\n\n- **Parameters**:\n  - `blocks`: The collection of coroutine blocks (of type `Func\u003cTask\u003e`) to execute in parallel.\n  - `dispatcher`: The dispatcher context for executing the coroutines. If `null`, the default dispatcher is used.\n  \n- **Returns**:\n  - A `Task` representing the asynchronous operation that completes once all coroutines have finished.\n\n#### 4.3 Launch Multiple Coroutines in Parallel (Synchronous)\n\n```csharp\npublic static async Task LaunchAll(IEnumerable\u003cAction\u003e blocks, Dispatcher dispatcher = null)\n```\nExecutes multiple synchronous coroutines (functions of type `Action`) in parallel and waits for all to complete.\n\n- **Parameters**:\n  - `blocks`: The collection of synchronous functions (of type `Action`) to execute in parallel.\n  - `dispatcher`: The dispatcher context for executing the functions. If `null`, the default dispatcher is used.\n  \n- **Returns**:\n  - A `Task` representing the asynchronous operation that completes once all functions have finished.\n\n\n### 5. CoroutineTimeout\n\n`CoroutineTimeout` provides utility methods for running coroutines with an applied timeout. If a coroutine does not complete within the specified time limit, a `TimeoutException` is thrown. This section explains how to use `CoroutineTimeout` to execute coroutines with a timeout.\n\n### Methods:\n\n#### 5.1 Run Coroutine with a Timeout (Returning a Value)\n\n```csharp\npublic static async Task\u003cT\u003e Run\u003cT\u003e(Func\u003cT\u003e coroutine, TimeSpan timeout, Dispatcher dispatcher = null)\n```\nRuns a coroutine that returns a value and applies a timeout. If the coroutine doesn't finish within the specified timeout, a `TimeoutException` is thrown.\n\n- **Parameters**:\n  - `coroutine`: The coroutine to execute, which returns a value of type `T`.\n  - `timeout`: The time span after which the coroutine will time out.\n  - `dispatcher`: The dispatcher context to execute the coroutine. If `null`, the default dispatcher is used.\n  \n- **Returns**:\n  - The result of the coroutine if it completes within the timeout period.\n\n- **Exceptions**:\n  - Throws a `TimeoutException` if the coroutine exceeds the specified timeout.\n\n#### 5.2 Run Coroutine with a Timeout (Returning No Value)\n\n```csharp\npublic static async Task Run(Action coroutine, TimeSpan timeout, Dispatcher dispatcher = null)\n```\nRuns a coroutine that takes no parameters and returns no value, with an applied timeout. If the coroutine doesn't finish within the specified timeout, a `TimeoutException` is thrown.\n\n- **Parameters**:\n  - `coroutine`: The coroutine to execute, which is a function of type `Action`.\n  - `timeout`: The time span after which the coroutine will time out.\n  - `dispatcher`: The dispatcher context to execute the coroutine. If `null`, the default dispatcher is used.\n  \n- **Returns**:\n  - A `Task` representing the asynchronous operation.\n\n- **Exceptions**:\n  - Throws a `TimeoutException` if the coroutine exceeds the specified timeout.\n\n#### 5.3 Run Coroutine with a Timeout (Returning a Task)\n\n```csharp\npublic static async Task\u003cT\u003e Run\u003cT\u003e(Func\u003cTask\u003cT\u003e\u003e coroutine, TimeSpan timeout, Dispatcher dispatcher = null)\n```\nRuns a coroutine that returns a `Task\u003cT\u003e` and applies a timeout. If the coroutine doesn't finish within the specified timeout, a `TimeoutException` is thrown.\n\n- **Parameters**:\n  - `coroutine`: The coroutine to execute, which returns a `Task\u003cT\u003e`.\n  - `timeout`: The time span after which the coroutine will time out.\n  - `dispatcher`: The dispatcher context to execute the coroutine. If `null`, the default dispatcher is used.\n  \n- **Returns**:\n  - The result of the coroutine if it completes within the timeout period.\n\n- **Exceptions**:\n  - Throws a `TimeoutException` if the coroutine exceeds the specified timeout.\n\n\n### 6. CoroutineScopeWithCancellation\n\n`CoroutineScopeWithCancellation` represents a coroutine scope with cancellation support for all coroutines within the scope. This class allows launching coroutines, waiting for them to complete, and canceling them when needed. If any coroutine in the scope is canceled, all coroutines within it are also canceled.\n\n### Constructor:\n\n#### 6.1 CoroutineScopeWithCancellation(Dispatcher context)\n\n```csharp\npublic CoroutineScopeWithCancellation(Dispatcher context)\n```\n- **Parameters**:\n  - `context`: The `Dispatcher` to use for the coroutines within the scope.\n  \n- **Description**:\n  Initializes a new instance of the `CoroutineScopeWithCancellation` class with the specified dispatcher.\n\n### Methods:\n\n#### 6.2 Launch Coroutine with Cancellation Support\n\n```csharp\npublic override async Task Launch(Func\u003cTask\u003e coroutine, Dispatcher dispatcher = null)\n```\n- **Parameters**:\n  - `coroutine`: The coroutine function to run. This should be an `async` function returning `Task`.\n  - `dispatcher`: The `Dispatcher` on which the coroutine should run. If `null`, the context dispatcher is used by default.\n  \n- **Description**:\n  Launches a coroutine within the scope. If a cancellation request is made for the scope, the coroutine will be canceled before execution completes.\n\n- **Exceptions**:\n  - Throws `OperationCanceledException` if the coroutine is canceled.\n  - Throws a generic `Exception` if any error occurs while executing the coroutine.\n\n#### 6.3 Launch Coroutine without Specified Dispatcher\n\n```csharp\npublic override async Task Launch(Func\u003cTask\u003e coroutine)\n```\n- **Parameters**:\n  - `coroutine`: The coroutine function to run.\n  \n- **Description**:\n  Launches a coroutine within the scope with cancellation support, using the default dispatcher. If a cancellation request is made for the scope, the coroutine will be canceled before execution completes.\n\n- **Exceptions**:\n  - Throws `OperationCanceledException` if the coroutine is canceled.\n  - Throws a generic `Exception` if any error occurs while executing the coroutine.\n\n#### 6.4 Cancel All Coroutines in the Scope\n\n```csharp\npublic void CancelAll()\n```\n- **Description**:\n  Cancels all coroutines currently running within the scope. This method can be called when you want to stop all ongoing coroutines in the scope.\n\n#### 6.5 Wait for All Coroutines to Complete with Cancellation Support\n\n```csharp\npublic new async Task WaitAllAsync()\n```\n- **Description**:\n  Waits for all coroutines within the scope to complete, with support for cancellation. If the scope is canceled, coroutines will stop running.\n\n- **Exceptions**:\n  - Throws `OperationCanceledException` if the coroutines are canceled.\n  - Throws a `CoroutineExecutionException` if an error occurs while waiting for coroutines to complete.\n\n\n### 7. Suspend\n\nThe `Suspend` class provides methods for suspending a coroutine for a specified duration or until a given condition is met. It offers various ways to delay execution, including waiting for a specific amount of time, waiting for a condition, or suspending for a set number of milliseconds or seconds.\n\n### Methods:\n\n#### 7.1 Suspend For a Duration\n\n```csharp\npublic static async Task For(TimeSpan duration)\n```\n- **Parameters**:\n  - `duration`: The amount of time to suspend the coroutine.\n  \n- **Description**:\n  Suspends the coroutine for the specified duration.\n\n- **Exceptions**:\n  - Throws `ArgumentOutOfRangeException` if the duration is negative.\n\n#### 7.2 Suspend for a Specific Number of Milliseconds\n\n```csharp\npublic static async Task ForMilliseconds(int milliseconds)\n```\n- **Parameters**:\n  - `milliseconds`: The number of milliseconds to suspend the coroutine.\n  \n- **Description**:\n  Suspends the coroutine for the specified number of milliseconds.\n\n- **Exceptions**:\n  - Throws `ArgumentOutOfRangeException` if the milliseconds value is negative.\n\n#### 7.3 Suspend for a Specific Number of Seconds\n\n```csharp\npublic static async Task ForSeconds(int seconds)\n```\n- **Parameters**:\n  - `seconds`: The number of seconds to suspend the coroutine.\n  \n- **Description**:\n  Suspends the coroutine for the specified number of seconds.\n\n- **Exceptions**:\n  - Throws `ArgumentOutOfRangeException` if the seconds value is negative.\n\n#### 7.4 Suspend Until a Condition is Met\n\n```csharp\npublic static async Task Until(Func\u003cbool\u003e condition, int checkIntervalMilliseconds = 100, int timeoutMilliseconds = -1)\n```\n- **Parameters**:\n  - `condition`: A function that returns a boolean indicating whether the condition is met.\n  - `checkIntervalMilliseconds`: The interval (in milliseconds) to check the condition. The default is 100 ms.\n  - `timeoutMilliseconds`: The maximum time to wait for the condition to be met, in milliseconds. A value of -1 means no timeout. The default is -1.\n\n- **Description**:\n  Suspends the coroutine until the given condition is met. The condition is checked periodically at the specified interval.\n\n- **Exceptions**:\n  - Throws `ArgumentNullException` if the condition is `null`.\n  - Throws `TimeoutException` if the condition is not met within the specified timeout.\n\n---\n\n## Examples\n\n### Example 1: **Combining GlobalScope, CoroutineBuilder, and Suspend**\n\nThis example demonstrates launching multiple coroutines using `GlobalScope` and `CoroutineBuilder`, suspending between operations using `Suspend`, and handling timeouts.\n\n```csharp\nusing System;\nusing System.Threading.Tasks;\nusing Coroutines;\n\nclass Program\n{\n    static async Task Main()\n    {\n        Console.WriteLine(\"Combining GlobalScope, CoroutineBuilder, and Suspend example started\");\n\n        // Launch multiple coroutines in parallel with CoroutineBuilder\n        await CoroutineBuilder.LaunchAll(new Func\u003cTask\u003e[]\n        {\n            async () =\u003e\n            {\n                await GlobalScope.Launch(async () =\u003e\n                {\n                    Console.WriteLine(\"Coroutine 1 started\");\n                    await Suspend.ForSeconds(2);\n                    Console.WriteLine(\"Coroutine 1 completed after 2 seconds\");\n                });\n            },\n            async () =\u003e\n            {\n                await GlobalScope.Launch(async () =\u003e\n                {\n                    Console.WriteLine(\"Coroutine 2 started\");\n                    await Suspend.ForSeconds(1);\n                    Console.WriteLine(\"Coroutine 2 completed after 1 second\");\n                });\n            }\n        });\n\n        // Adding a timeout example with CoroutineTimeout\n        try\n        {\n            await CoroutineTimeout.Run(async () =\u003e\n            {\n                await Task.Delay(5000); // Simulate a long-running task\n                Console.WriteLine(\"Long task completed\");\n            }, TimeSpan.FromSeconds(3)); // Timeout after 3 seconds\n        }\n        catch (TimeoutException)\n        {\n            Console.WriteLine(\"The long task timed out.\");\n        }\n\n        Console.WriteLine(\"Combining example completed\");\n    }\n}\n```\n\n**Output:**\n```\nCombining GlobalScope, CoroutineBuilder, and Suspend example started\nCoroutine 1 started\nCoroutine 2 started\nCoroutine 2 completed after 1 second\nCoroutine 1 completed after 2 seconds\nThe long task timed out.\nCombining example completed\n```\n\n### Example Explanation:\n1. **GlobalScope** is used to launch individual coroutines.\n2. **CoroutineBuilder** runs multiple coroutines in parallel.\n3. **Suspend** is used to introduce delays between tasks.\n4. **CoroutineTimeout** is used to handle tasks that might take too long.\n\n---\n\n### Example 2: **Combining CoroutineScopeWithCancellation and CoroutineBuilder**\n\nThis example shows how to launch tasks in a `CoroutineScopeWithCancellation`, cancel them, and handle errors.\n\n```csharp\nusing System;\nusing System.Threading.Tasks;\nusing Coroutines;\n\nclass Program\n{\n    static async Task Main()\n    {\n        Console.WriteLine(\"Combining CoroutineScopeWithCancellation and CoroutineBuilder example started\");\n\n        // Create a new CoroutineScopeWithCancellation\n        var scope = new CoroutineScopeWithCancellation(Dispatcher.Default);\n\n        // Launch multiple coroutines inside the scope\n        var coroutine1 = scope.Launch(async () =\u003e\n        {\n            Console.WriteLine(\"Coroutine 1 started\");\n            await Suspend.ForSeconds(3); // Simulate long-running task\n            Console.WriteLine(\"Coroutine 1 completed\");\n        });\n\n        var coroutine2 = scope.Launch(async () =\u003e\n        {\n            Console.WriteLine(\"Coroutine 2 started\");\n            await Suspend.ForSeconds(1);\n            Console.WriteLine(\"Coroutine 2 completed\");\n        });\n\n        // Cancel all coroutines in the scope after 2 seconds\n        await Task.Delay(2000); \n        scope.CancelAll(); // This will cancel coroutine1\n\n        // Wait for the coroutines to complete\n        await scope.WaitAllAsync(); \n\n        Console.WriteLine(\"Combining example completed\");\n    }\n}\n```\n\n**Output:**\n```\nCombining CoroutineScopeWithCancellation and CoroutineBuilder example started\nCoroutine 1 started\nCoroutine 2 started\nCoroutine 2 completed\nCoroutine was canceled.\nCombining example completed\n```\n\n### Example Explanation:\n1. **CoroutineScopeWithCancellation** is used to group multiple coroutines and handle cancellation.\n2. **CoroutineBuilder** launches coroutines inside the scope.\n3. **Suspend** is used for delays.\n4. The scope is canceled after 2 seconds, interrupting the long-running task.\n\n---\n\n### Example 3: **Combining CoroutineTimeout and Suspend with Error Handling**\n\nThis example demonstrates combining timeout handling with suspension.\n\n```csharp\nusing System;\nusing System.Threading.Tasks;\nusing Coroutines;\n\nclass Program\n{\n    static async Task Main()\n    {\n        Console.WriteLine(\"Combining CoroutineTimeout and Suspend with Error Handling example started\");\n\n        // Example with CoroutineTimeout\n        try\n        {\n            await CoroutineTimeout.Run(async () =\u003e\n            {\n                Console.WriteLine(\"Starting long task...\");\n                await Suspend.ForSeconds(5); // Simulate long task\n                Console.WriteLine(\"Long task completed\");\n            }, TimeSpan.FromSeconds(3)); // Timeout after 3 seconds\n        }\n        catch (TimeoutException)\n        {\n            Console.WriteLine(\"The long task timed out.\");\n        }\n\n        // Another example with CoroutineTimeout and no timeout\n        try\n        {\n            await CoroutineTimeout.Run(async () =\u003e\n            {\n                Console.WriteLine(\"Starting short task...\");\n                await Suspend.ForSeconds(1); // Short task\n                Console.WriteLine(\"Short task completed\");\n            }, TimeSpan.FromSeconds(3)); // No timeout\n        }\n        catch (TimeoutException)\n        {\n            Console.WriteLine(\"The short task timed out.\");\n        }\n\n        Console.WriteLine(\"Combining example completed\");\n    }\n}\n```\n\n**Output:**\n```\nCombining CoroutineTimeout and Suspend with Error Handling example started\nStarting long task...\nThe long task timed out.\nStarting short task...\nShort task completed\nCombining example completed\n```\n\n### Example Explanation:\n1. **CoroutineTimeout** is used to limit how long a task can run.\n2. **Suspend** is used to simulate long and short tasks.\n3. **TimeoutException** is handled to deal with tasks that take too long.\n\n---\n\n### Example 4: **Combining GlobalScope, Suspend, and CoroutineScopeWithCancellation for a Health Monitoring System**\n\nIn a more complex scenario, such as monitoring environmental factors (for instance, air quality), we can combine all concepts into one solution.\n\n```csharp\nusing System;\nusing System.Threading.Tasks;\nusing Coroutines;\n\nclass HealthMonitor\n{\n    public async Task StartMonitoring()\n    {\n        Console.WriteLine(\"Health Monitor started\");\n\n        // Create a CoroutineScopeWithCancellation for the entire health monitoring session\n        var monitorScope = new CoroutineScopeWithCancellation(Dispatcher.Default);\n\n        // Launch air quality monitoring coroutine\n        var airQualityMonitor = monitorScope.Launch(async () =\u003e\n        {\n            Console.WriteLine(\"Monitoring air quality...\");\n            await Suspend.ForSeconds(2); // Simulate time taken for measuring air quality\n            Console.WriteLine(\"Air quality is good.\");\n        });\n\n        // Launch temperature monitoring coroutine\n        var temperatureMonitor = monitorScope.Launch(async () =\u003e\n        {\n            Console.WriteLine(\"Monitoring temperature...\");\n            await Suspend.ForSeconds(1);\n            Console.WriteLine(\"Temperature is normal.\");\n        });\n\n        // Simulate a condition for scope cancellation\n        await Task.Delay(1500);\n        monitorScope.CancelAll(); // Cancel all coroutines\n\n        // Wait for all coroutines to complete or handle cancellation\n        await monitorScope.WaitAllAsync();\n\n        Console.WriteLine(\"Health Monitor session completed\");\n    }\n}\n\nclass Program\n{\n    static async Task Main()\n    {\n        var monitor = new HealthMonitor();\n        await monitor.StartMonitoring();\n    }\n}\n```\n\n**Output:**\n```\nHealth Monitor started\nMonitoring air quality...\nMonitoring temperature...\nTemperature is normal.\nCoroutine was canceled.\nHealth Monitor session completed\n```\n\n### Example Explanation:\n1. **GlobalScope** is not needed in this scenario, as **CoroutineScopeWithCancellation** is used to group monitoring tasks.\n2. **Suspend** is used to simulate the delays in monitoring different parameters.\n3. After a delay, **CancelAll** cancels the air quality monitoring coroutine, demonstrating how to manage coroutines within a scope.\n\n---\n\n### Conclusion\n\nThis coroutine library provides a robust and flexible framework for managing asynchronous tasks in C#. With support for multiple dispatchers, cancellation, error handling, and scope management, it is a powerful tool for any application requiring efficient asynchronous task management.\n\nFor advanced use cases or to contribute, please check the [source code](https://github.com/yourusername/coroutines).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstyropyr0%2Fcoroutines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstyropyr0%2Fcoroutines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstyropyr0%2Fcoroutines/lists"}