Tag Archives: task
C# || How To Create Multiple Tasks With Maximum Concurrency Using C#
The following is a module with functions which demonstrates how to create multiple tasks with maximum concurrency using C#.
The examples demonstrated on this page uses System.Threading.Tasks.Task to start and run tasks. They also use System.Threading.SemaphoreSlim to limit the number of tasks that can run concurrently.
The examples on this page demonstrates how to start and run multiple tasks with a maximum concurrency. It also demonstrates how to start and run multiple tasks with a return value.
1. Task – Maximum Concurrency
The example below demonstrates how to start and run multiple tasks with a maximum concurrency. For example purposes, the tasks do not return a value.
The functions shown in the example below are called asynchronously, but they can also be called synchronously.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
// Task - Maximum Concurrency var concurrentTasks = 5; var semaphore = new System.Threading.SemaphoreSlim(concurrentTasks, concurrentTasks); var tasks = new List<System.Threading.Tasks.Task>(); for (var count = 1; count <= 20; ++count) { var taskNumber = count; // Blocks execution until another task can be started. // This function also accepts a timeout in milliseconds await semaphore.WaitAsync(); // Start a task var task = System.Threading.Tasks.Task.Run(async () => { // Execute long running code try { Console.WriteLine($"Task #{taskNumber} starting..."); await System.Threading.Tasks.Task.Delay(5000); Console.WriteLine($" - Task #{taskNumber} completed!"); } catch { throw; } finally { // Signal that the task is completed // so another task can start semaphore.Release(); } }); tasks.Add(task); } Console.WriteLine($"Waiting for tasks to complete"); // Wait for all tasks to complete await System.Threading.Tasks.Task.WhenAll(tasks.ToArray()); Console.WriteLine($"All tasks completed!"); // example output: /* Task #2 starting... Task #1 starting... Task #3 starting... Task #5 starting... Task #4 starting... - Task #3 completed! - Task #1 completed! Task #6 starting... - Task #4 completed! - Task #2 completed! Task #8 starting... Task #9 starting... - Task #5 completed! Task #7 starting... Task #10 starting... - Task #6 completed! Task #11 starting... - Task #8 completed! Task #12 starting... - Task #9 completed! Task #13 starting... - Task #7 completed! - Task #10 completed! Task #14 starting... Task #15 starting... - Task #11 completed! Task #16 starting... - Task #12 completed! Task #17 starting... - Task #13 completed! Task #18 starting... - Task #14 completed! - Task #15 completed! Task #19 starting... Waiting for tasks to complete Task #20 starting... - Task #16 completed! - Task #17 completed! - Task #18 completed! - Task #20 completed! - Task #19 completed! All tasks completed! */ |
2. Task – Maximum Concurrency – Return Value
The example below demonstrates how to start and run multiple tasks with a maximum concurrency. In this example, a value is returned and retrieved from the tasks
The functions shown in the example below are called asynchronously, but they can also be called synchronously.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
// Task - Maximum Concurrency - Return Value public class Part { public string PartName { get; set; } public int PartId { get; set; } } var concurrentTasks = 5; var semaphore = new System.Threading.SemaphoreSlim(concurrentTasks, concurrentTasks); var tasks = new List<System.Threading.Tasks.Task<Part>>(); for (var count = 1; count <= 20; ++count) { var taskNumber = count; // Blocks execution until another task can be started. // This function also accepts a timeout in milliseconds await semaphore.WaitAsync(); // Start a task var task = System.Threading.Tasks.Task.Run(async () => { // Execute long running code try { Console.WriteLine($"Task #{taskNumber} starting..."); await System.Threading.Tasks.Task.Delay(5000); Console.WriteLine($" - Task #{taskNumber} completed!"); // Return result return new Part() { PartId = taskNumber, PartName = $"Part #{taskNumber}" }; } catch { throw; } finally { // Signal that the task is completed // so another task can start semaphore.Release(); } }); tasks.Add(task); } Console.WriteLine($"Waiting for tasks to complete"); // Wait for all tasks to complete await System.Threading.Tasks.Task.WhenAll(tasks.ToArray()); Console.WriteLine($"All tasks completed!"); Console.WriteLine(""); // Get the results foreach (var task in tasks) { var part = task.Result; Console.WriteLine($"Id: {part.PartId}, Name: {part.PartName}"); } // example output: /* Task #1 starting... Task #2 starting... Task #3 starting... Task #4 starting... Task #5 starting... - Task #3 completed! - Task #1 completed! Task #6 starting... - Task #5 completed! - Task #2 completed! Task #8 starting... Task #7 starting... Task #9 starting... - Task #4 completed! Task #10 starting... - Task #6 completed! Task #11 starting... - Task #8 completed! Task #12 starting... - Task #7 completed! Task #13 starting... - Task #10 completed! - Task #9 completed! Task #14 starting... Task #15 starting... - Task #11 completed! Task #16 starting... - Task #12 completed! Task #17 starting... - Task #13 completed! Task #18 starting... - Task #15 completed! - Task #14 completed! Task #19 starting... Waiting for tasks to complete Task #20 starting... - Task #17 completed! - Task #16 completed! - Task #18 completed! - Task #19 completed! - Task #20 completed! All tasks completed! Id: 1, Name: Part #1 Id: 2, Name: Part #2 Id: 3, Name: Part #3 Id: 4, Name: Part #4 Id: 5, Name: Part #5 Id: 6, Name: Part #6 Id: 7, Name: Part #7 Id: 8, Name: Part #8 Id: 9, Name: Part #9 Id: 10, Name: Part #10 Id: 11, Name: Part #11 Id: 12, Name: Part #12 Id: 13, Name: Part #13 Id: 14, Name: Part #14 Id: 15, Name: Part #15 Id: 16, Name: Part #16 Id: 17, Name: Part #17 Id: 18, Name: Part #18 Id: 19, Name: Part #19 Id: 20, Name: Part #20 */ |
3. More Examples
Below is a full example of the process demonstrated on this page!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
// ============================================================================ // Author: Kenneth Perkins // Date: May 15, 2021 // Taken From: http://programmingnotes.org/ // File: Program.cs // Description: The following demonstrates creating a task pool // ============================================================================ using System; using System.Diagnostics; using System.Linq; using System.Collections.Generic; using System.Threading.Tasks; public class Program { public class Part { public string PartName { get; set; } public int? PartId { get; set; } } static void Main(string[] args) { try { //TaskVoid().Wait(); TaskFunction().Wait(); } catch (Exception ex) { Display(ex.ToString()); } finally { Console.ReadLine(); } } public static async Task<List<Part>> TaskFunction() { var concurrentTasks = 5; var semaphore = new System.Threading.SemaphoreSlim(concurrentTasks, concurrentTasks); var tasks = new List<System.Threading.Tasks.Task<Part>>(); for (var count = 1; count <= 20; ++count) { var taskNumber = count; // Blocks execution until another task can be started. // This function also accepts a timeout in milliseconds await semaphore.WaitAsync(); // Start a task var task = System.Threading.Tasks.Task.Run(async () => { // Execute long running code try { Display($"Task #{taskNumber} starting..."); await System.Threading.Tasks.Task.Delay(5000); Display($" - Task #{taskNumber} completed!"); // Return result return new Part() { PartId = taskNumber, PartName = $"Part #{taskNumber}" }; } catch { throw; } finally { // Signal that the task is completed // so another task can start semaphore.Release(); } }); tasks.Add(task); } Display($"Waiting for tasks to complete"); // Wait for all tasks to complete await System.Threading.Tasks.Task.WhenAll(tasks.ToArray()); Display($"All tasks completed!"); Display(""); // Get the results foreach (var task in tasks) { var part = task.Result; Display($"Id: {part.PartId}, Name: {part.PartName}"); } return tasks.Select(task => task.Result).ToList(); } public static async Task TaskVoid() { var concurrentTasks = 5; var semaphore = new System.Threading.SemaphoreSlim(concurrentTasks, concurrentTasks); var tasks = new List<System.Threading.Tasks.Task>(); for (var count = 1; count <= 20; ++count) { var taskNumber = count; // Blocks execution until another task can be started. // This function also accepts a timeout in milliseconds await semaphore.WaitAsync(); // Start a task var task = System.Threading.Tasks.Task.Run(async () => { // Execute long running code try { Display($"Task #{taskNumber} starting..."); await System.Threading.Tasks.Task.Delay(5000); Display($" - Task #{taskNumber} completed!"); } catch { throw; } finally { // Signal that the task is completed // so another task can start semaphore.Release(); } }); tasks.Add(task); } Display($"Waiting for tasks to complete"); // Wait for all tasks to complete await System.Threading.Tasks.Task.WhenAll(tasks.ToArray()); Display($"All tasks completed!"); } static void Display(string message) { Console.WriteLine(message); Debug.Print(message); } }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
VB.NET || How To Create Multiple Tasks With Maximum Concurrency Using VB.NET
The following is a module with functions which demonstrates how to create multiple tasks with maximum concurrency using VB.NET.
The examples demonstrated on this page uses System.Threading.Tasks.Task to start and run tasks. They also use System.Threading.SemaphoreSlim to limit the number of tasks that can run concurrently.
The examples on this page demonstrates how to start and run multiple tasks with a maximum concurrency. It also demonstrates how to start and run multiple tasks with a return value.
1. Task – Maximum Concurrency
The example below demonstrates how to start and run multiple tasks with a maximum concurrency. For example purposes, the tasks do not return a value.
The functions shown in the example below are called asynchronously, but they can also be called synchronously.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
' Task - Maximum Concurrency Dim concurrentTasks = 5 Dim semaphore = New System.Threading.SemaphoreSlim(concurrentTasks, concurrentTasks) Dim tasks = New List(Of System.Threading.Tasks.Task) For count = 1 To 20 Dim taskNumber = count ' Blocks execution until another task can be started. ' This function also accepts a timeout in milliseconds Await semaphore.WaitAsync() ' Start a task Dim task = System.Threading.Tasks.Task.Run(Async Function() ' Execute long running code Try Debug.Print($"Task #{taskNumber} starting...") Await System.Threading.Tasks.Task.Delay(5000) Debug.Print($" - Task #{taskNumber} completed!") Catch ex As Exception Throw Finally ' Signal that the task is completed ' so another task can start semaphore.Release() End Try End Function) tasks.Add(task) Next Debug.Print($"Waiting for tasks to complete") ' Wait for all tasks to complete Await System.Threading.Tasks.Task.WhenAll(tasks.ToArray) Debug.Print($"All tasks completed!") ' example output: ' Task #1 starting... ' Task #2 starting... ' Task #3 starting... ' Task #4 starting... ' Task #5 starting... ' - Task #1 completed! ' - Task #2 completed! ' Task #6 starting... ' Task #7 starting... ' - Task #4 completed! ' - Task #3 completed! ' - Task #5 completed! ' Task #8 starting... ' Task #9 starting... ' Task #10 starting... ' - Task #7 completed! ' - Task #6 completed! ' Task #11 starting... ' Task #12 starting... ' - Task #9 completed! ' - Task #10 completed! ' Task #13 starting... ' Task #14 starting... ' - Task #8 completed! ' Task #15 starting... ' - Task #12 completed! ' - Task #11 completed! ' Task #16 starting... ' Task #17 starting... ' - Task #14 completed! ' - Task #13 completed! ' - Task #15 completed! ' Task #19 starting... ' Waiting for tasks to complete ' Task #18 starting... ' Task #20 starting... ' - Task #17 completed! ' - Task #16 completed! ' - Task #19 completed! ' - Task #20 completed! ' - Task #18 completed! ' All tasks completed! |
2. Task – Maximum Concurrency – Return Value
The example below demonstrates how to start and run multiple tasks with a maximum concurrency. In this example, a value is returned and retrieved from the tasks
The functions shown in the example below are called asynchronously, but they can also be called synchronously.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
' Task - Maximum Concurrency - Return Value Public Class Part Public Property PartName As String Public Property PartId As Integer End Class Dim concurrentTasks = 5 Dim semaphore = New System.Threading.SemaphoreSlim(concurrentTasks, concurrentTasks) Dim tasks = New List(Of System.Threading.Tasks.Task(Of Part)) For count = 1 To 20 Dim taskNumber = count ' Blocks execution until another task can be started. ' This function also accepts a timeout in milliseconds Await semaphore.WaitAsync() ' Start a task Dim task = System.Threading.Tasks.Task.Run(Async Function() ' Execute long running code Try Debug.Print($"Task #{taskNumber} starting...") Await System.Threading.Tasks.Task.Delay(5000) Debug.Print($" - Task #{taskNumber} completed!") ' Return result Return New Part With { .PartId = taskNumber, .PartName = $"Part #{taskNumber}" } Catch ex As Exception Throw Finally ' Signal that the task is completed ' so another task can start semaphore.Release() End Try End Function) tasks.Add(task) Next Debug.Print($"Waiting for tasks to complete") ' Wait for all tasks to complete Await System.Threading.Tasks.Task.WhenAll(tasks.ToArray) Debug.Print($"All tasks completed!") Debug.Print("") ' Get the results For Each task In tasks Dim part = task.Result Debug.Print($"Id: {part.PartId}, Name: {part.PartName}") Next ' example output: ' Task #1 starting... ' Task #2 starting... ' Task #3 starting... ' Task #4 starting... ' Task #5 starting... ' - Task #3 completed! ' - Task #2 completed! ' - Task #5 completed! ' - Task #1 completed! ' Task #8 starting... ' Task #7 starting... ' Task #6 starting... ' - Task #4 completed! ' Task #9 starting... ' Task #10 starting... ' - Task #8 completed! ' Task #11 starting... ' - Task #7 completed! ' Task #12 starting... ' - Task #6 completed! ' Task #13 starting... ' - Task #10 completed! ' - Task #9 completed! ' Task #14 starting... ' Task #15 starting... ' - Task #11 completed! ' Task #16 starting... ' - Task #12 completed! ' Task #17 starting... ' - Task #13 completed! ' Task #18 starting... ' - Task #15 completed! ' - Task #14 completed! ' Task #19 starting... ' Waiting for tasks to complete ' Task #20 starting... ' - Task #16 completed! ' - Task #17 completed! ' - Task #18 completed! ' - Task #19 completed! ' - Task #20 completed! ' All tasks completed! ' ' Id: 1, Name: Part #1 ' Id: 2, Name: Part #2 ' Id: 3, Name: Part #3 ' Id: 4, Name: Part #4 ' Id: 5, Name: Part #5 ' Id: 6, Name: Part #6 ' Id: 7, Name: Part #7 ' Id: 8, Name: Part #8 ' Id: 9, Name: Part #9 ' Id: 10, Name: Part #10 ' Id: 11, Name: Part #11 ' Id: 12, Name: Part #12 ' Id: 13, Name: Part #13 ' Id: 14, Name: Part #14 ' Id: 15, Name: Part #15 ' Id: 16, Name: Part #16 ' Id: 17, Name: Part #17 ' Id: 18, Name: Part #18 ' Id: 19, Name: Part #19 ' Id: 20, Name: Part #20 |
3. More Examples
Below is a full example of the process demonstrated on this page!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
' ============================================================================ ' Author: Kenneth Perkins ' Date: Dec 4, 2020 ' Taken From: http://programmingnotes.org/ ' File: Program.vb ' Description: The following demonstrates creating a task pool ' ============================================================================ Option Strict On Option Explicit On Imports System Public Module Program Public Class Part Public Property PartName As String Public Property PartId As Integer End Class Sub Main(args As String()) Try 'TaskSub.Wait() TaskFunction.Wait() Catch ex As Exception Display(ex.ToString) Finally Console.ReadLine() End Try End Sub Public Async Function TaskFunction() As Task(Of List(Of Part)) Dim concurrentTasks = 5 Dim semaphore = New System.Threading.SemaphoreSlim(concurrentTasks, concurrentTasks) Dim tasks = New List(Of System.Threading.Tasks.Task(Of Part)) For count = 1 To 20 Dim taskNumber = count ' Blocks execution until another task can be started. ' This function also accepts a timeout in milliseconds Await semaphore.WaitAsync() ' Start a task Dim task = System.Threading.Tasks.Task.Run(Async Function() ' Execute long running code Try Display($"Task #{taskNumber} starting...") Await System.Threading.Tasks.Task.Delay(5000) Display($" - Task #{taskNumber} completed!") Return New Part With { .PartId = taskNumber, .PartName = $"Part #{taskNumber}" } Catch ex As Exception Throw Finally ' Signal that the task is completed ' so another task can start semaphore.Release() End Try End Function) tasks.Add(task) Next Display($"Waiting for tasks to complete") ' Wait for all tasks to complete Await System.Threading.Tasks.Task.WhenAll(tasks.ToArray) Display($"All tasks completed!") Display("") ' Get the results For Each task In tasks Dim part = task.Result Display($"Id: {part.PartId}, Name: {part.PartName}") Next Return tasks.Select(Function(task) task.Result).ToList End Function Public Async Function TaskSub() As Task Dim concurrentTasks = 5 Dim semaphore = New System.Threading.SemaphoreSlim(concurrentTasks, concurrentTasks) Dim tasks = New List(Of System.Threading.Tasks.Task) For count = 1 To 20 Dim taskNumber = count ' Blocks execution until another task can be started. ' This function also accepts a timeout in milliseconds Await semaphore.WaitAsync() ' Start a task Dim task = System.Threading.Tasks.Task.Run(Async Function() ' Execute long running code Try Display($"Task #{taskNumber} starting...") Await System.Threading.Tasks.Task.Delay(5000) Display($" - Task #{taskNumber} completed!") Catch ex As Exception Throw Finally ' Signal that the task is completed ' so another task can start semaphore.Release() End Try End Function) tasks.Add(task) Next Display($"Waiting for tasks to complete") ' Wait for all tasks to complete Await System.Threading.Tasks.Task.WhenAll(tasks.ToArray) Display($"All tasks completed!") End Function Public Sub Display(message As String) Console.WriteLine(message) Debug.Print(message) End Sub End Module ' http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.