Categories
C# Tasks

Processing Tasks in Order of Completion

Disclaimer: I acknowledge this method was obtained from another blog; I’m pretty sure it was Stephen Toub’s, but I cannot seem to find his post again.

But here are my modified versions of his Interleaved() method.

#nullable enable

	using System;
	using System.Collections.Concurrent;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.Linq;
	using System.Threading;
	using System.Threading.Tasks;
	using JetBrains.Annotations;

	public static class TaskExtensions {

		/// <summary>
		/// Return tasks in order of completion.
		/// </summary>
		/// <param name="tasks"></param>
		/// <returns></returns>
		public static IEnumerable<Task<Task>> InOrderOfCompletion( this IEnumerable<Task> tasks ) {
			var inputTasks = tasks.ToList();

			var buckets = new TaskCompletionSource<Task>[ inputTasks.Count ];
			var results = new Task<Task>[ buckets.Length ];

			for ( var i = 0; i < buckets.Length; i++ ) {
				buckets[ i ] = new TaskCompletionSource<Task>();
				results[ i ] = buckets[ i ].Task;
			}

			var nextTaskIndex = -1;

			void Continuation( Task completed ) {
				var bucket = buckets[ Interlocked.Increment( ref nextTaskIndex ) ];
				bucket.TrySetResult( completed );
			}

			foreach ( var inputTask in inputTasks ) {
				inputTask?.ContinueWith( Continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default );
			}

			return results;
		}

		/// <summary>
		/// Return tasks in order of completion.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="tasks"></param>
		/// <returns></returns>
		[ItemNotNull]
		[NotNull]
		public static IEnumerable<Task<Task<T>>> InOrderOfCompletion<T>( this IEnumerable<Task<T>> tasks ) {
			var inputTasks = tasks.ToList();

			var buckets = new TaskCompletionSource<Task<T>>[ inputTasks.Count ];
			var results = new Task<Task<T>>[ buckets.Length ];

			for ( var i = 0; i < buckets.Length; i++ ) {
				buckets[ i ] = new TaskCompletionSource<Task<T>>();
				results[ i ] = buckets[ i ].Task;
			}

			var nextTaskIndex = -1;

			void Continuation( Task<T> completed ) {
				var bucket = buckets[ Interlocked.Increment( ref nextTaskIndex ) ];
				bucket.TrySetResult( completed );
			}

			foreach ( var inputTask in inputTasks ) {
				inputTask?.ContinueWith( Continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default );
			}

			return results;
		}

		/// <summary>
		/// Return tasks in order of completion.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="tasks"></param>
		/// <returns></returns>
		[ItemNotNull]
		[NotNull]
		public static IEnumerable<Task<Task<T>>> InOrderOfCompletion<T>( this IDictionary<TimeSpan, Task<T>> tasks ) {
			var inputTasks = tasks.ToList();

			var buckets = new TaskCompletionSource<Task<T>>[ inputTasks.Count ];
			var results = new Task<Task<T>>[ buckets.Length ];

			for ( var i = 0; i < buckets.Length; i++ ) {
				buckets[ i ] = new TaskCompletionSource<Task<T>>();
				results[ i ] = buckets[ i ].Task;
			}

			var nextTaskIndex = -1;

			void Continuation( Task<T> completed ) {
				var bucket = buckets[ Interlocked.Increment( ref nextTaskIndex ) ];
				bucket.TrySetResult( completed );
			}

			foreach ( var inputTask in inputTasks ) {
				inputTask.Value?.ContinueWith( Continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default );
			}

			return results;
		}

	}

And here is my test code.

	public static class Examples {

		public static async Task TestsInOrderOfCompletion( CancellationToken token ) {
			var rng = new Random();

			//Add to the list, out of "order"..
			var tasks = new ConcurrentDictionary<TimeSpan, Task<String>> {
				[ TimeSpan.FromSeconds( 3 ) ] = Task.Delay( TimeSpan.FromSeconds( 3 ), token ).ContinueWith( _ => "3 seconds", token ),
				[ TimeSpan.FromSeconds( 1 ) ] = Task.Delay( TimeSpan.FromSeconds( 1 ), token ).ContinueWith( _ => "1 second", token ),
				[ TimeSpan.FromSeconds( 2 ) ] = Task.Delay( TimeSpan.FromSeconds( 2 ), token ).ContinueWith( _ => "2 seconds", token ),
				[ TimeSpan.FromSeconds( 5 ) ] = Task.Delay( TimeSpan.FromSeconds( 5 ), token ).ContinueWith( _ => "5 seconds", token ),
				[ TimeSpan.FromSeconds( 8 ) ] = Task.Delay( TimeSpan.FromSeconds( 8 ), token ).ContinueWith( _ => "8 seconds", token ),
				[ TimeSpan.FromSeconds( 7 ) ] = Task.Delay( TimeSpan.FromSeconds( 7 ), token ).ContinueWith( _ => "7 seconds", token ),
				[ TimeSpan.FromSeconds( 9 ) ] = Task.Delay( 1000, token ).ContinueWith( _ => "9 seconds", token ),
				[ TimeSpan.FromSeconds( 10 ) ] = Task.Delay( 1000, token ).ContinueWith( _ => "10 seconds", token ),
				[ TimeSpan.FromSeconds( 4 ) ] = Task.Delay( 1000, token ).ContinueWith( _ => "4 seconds", token )
			};

			//Add a few more to the list, also in "random" order..
			for ( var i = 0; i < 25; i++ ) {
				var millisecondsDelay = rng.Next( 10000 );
				var task = Task.Delay( millisecondsDelay, token ).ContinueWith( _ => $"{millisecondsDelay / 1000.0:F4}", token );   //return how many milliseconds we just delayed
				tasks[ TimeSpan.FromMilliseconds( millisecondsDelay ) ] = task;
			}

			foreach ( var bucket in tasks.InOrderOfCompletion() ) {
				try {
					var task = await bucket.ConfigureAwait( false );
					var result = await task.ConfigureAwait( false );
					Console.WriteLine( $"{DateTime.Now:hh:mm:ss}, TaskId #{task.Id:N0}, {result} ms" );

				}
				catch ( OperationCanceledException ) { }

				catch ( Exception exception ) {
					Debug.WriteLineIf( Debugger.IsAttached, exception.ToString() );
				}
			}

		}

	}
Categories
Articles C# Developers

The 4 pillars of OOP (Object Oriented Programming) summed up in my own words.

Encapsulation – The process of hiding internal data away from other classes.

Abstraction – The process of hiding irrelevant details while providing a feature.
(with the side effect of reducing the code complexity.)

Inheritance – The process of providing properties and methods to derived classes.

Polymorphism – The ability of a derived class to take on different behaviors than the parent class provides.

Categories
C#

Magical Methods in C#

Here is a very well written article about various capabilities in C# written by CEZARY PIÄ„TEK.
The Magical Methods in C#

Categories
C#

Curly {braces} Matter!

Blocks like “if“, “for“, “while“, and “using” (and others) should always use the curly braces “{” and “}“.

Code is for humans to read, and compilers to compile. Right?

By properly adding these braces ahead of time before they are needed, you future-proof the code and make the code’s intention (the logic) clear to any future programmer (including yourself).

This is not from an OCD formatting-enthusiast perspective. This is from decades of experience with C# and other {}-like languages.

Sure, one liners do work and they do reduce the total count of lines, but they are prone to bugs that are not immediately apparent to other programmers, compilers, code formatters, or via indentation.

If you use them, that is fine. Just be aware of the potential for issues in the future when someone edits the code.

BTW, If you can provide a reproducible example that causes C# code fail to compile, break, bug out, or crash by adding the proper braces, then please let me know! I’d greatly appreciate it.

Formatters cannot detect the original intent of the programmer. If even a single line of logic is missed (or ran when it should not), then the results of the function, method, or even the whole program could be affected.

Please, Do not write code to the lowest common denominator.

(I’ll link a gist if I ever get a better example completed.)
Here is a simplified example.

public static void RolRorRolRol( ref this UInt64 ul, Int32 n ) {
	if ( n > 2 )
		ul = ( ul << 3 ) | ( ul >> ( 64 - 3 ) );
	if ( ul < 10 )
		ul = ( ul << ( 64 - 4 ) ) | ( ul >> 4 );
	ul = ( ul << 5 ) | ( ul >> ( 64 - 5 ) );
	ul = ( ul << 6 ) | ( ul >> ( 64 - 6 ) );
}

Here is the “corrected” example.

public static void RolRorRolRol( ref this UInt64 ul, Int32 n ) {
	if ( n > 2 ) {
		ul = ( ul << 3 ) | ( ul >> ( 64 - 3 ) );
	}

	if ( ul < 10 ) {
		ul = ( ul << ( 64 - 4 ) ) | ( ul >> 4 );
		ul = ( ul << 5 ) | ( ul >> ( 64 - 5 ) );
	}

	ul = ( ul << 6 ) | ( ul >> ( 64 - 6 ) );
}
Categories
C#

Ordering of static fields in C# matters

via Ordering of static fields in C# matters

The ordering of static fields does matter.
But per your examples, here is the pattern I always use:

public class Person {
    private static EmptyPerson _emptyPerson;
    public static Person Empty => _emptyPerson ?? ( _emptyPerson = new EmptyPerson() );
}

The allows the Empty value to be initialized once and read-only, yet still used many times.

It also hides away the requirements of the initialization (the value pulled from a database for example) from the public getter. We could even put the value into a Lazy<Person>().

And in C# 8 we now have the compound assignment!

public class Person {
    private static EmptyPerson _emptyPerson;
    public static Person Empty => _emptyPerson ??= new EmptyPerson();
}
Categories
C#

Writing xUnit Tests in .NET Core

RE: Writing xUnit Tests in .NET Core — Visual Studio Magazine

Very nice example and explanations!
They even show how to pass in multiple values to test with.

Thank you!

Categories
Benchmarking C#

Big-O Algorithm Complexity Cheat Sheet

via Big-O Algorithm Complexity Cheat Sheet (Know Thy Complexities!) @ericdrowell

Nice! Thanks!

Categories
C#

C# Async Tips & Tricks

via C# Async Tips & Tricks

Helpful material !

Categories
C#

What’s new in the .NET Framework 4.7.2!

The 4.7.2 .NET Framework has been released! You can now download the SDK and the runtime here.

What’s New in the .NET Framework (4.7.2 edition)