Enforcing C# Task to exist only once at any given point of time for a given ID
What's the point of _continuations? I can see three options which use a single dictionary:


Just store and return concreteTask. If this fails because the continuation is GC'd, document this for the benefit of maintainers.
Just store and return the continuation. If this fails because the continuation is executed multiple times, document it.
Store the task and return the continuation, so the first caller has the hard reference. I can't think how this could fail unless the caller actively discards the task.


TL;DR: if there are obvious ways of simplifying the code which break for non-obvious reasons, document the reasons so that the maintainer doesn't break it.



A further advantage of using a single dictionary would be that you could use ConcurrentDictionary instead of the manual locking. (In fact you could do this even if you do need both copies of the task, using ConcurrentDictionary&lt;string, Tuple&lt;Task, Task&gt;&gt;). The code might be as simple as

    public class TaskManager : ITaskManager
    {
        private readonly ConcurrentDictionary&lt;string, Task&gt; _tasks = new ConcurrentDictionary&lt;string, Task&gt;();

        public Task&lt;T&gt; ExecuteOnceAsync&lt;T&gt;(string taskId, Func&lt;Task&lt;T&gt;&gt; taskFactory)
        {
            var task = _tasks.GetOrAdd(
                taskId,
                id =&gt; taskFactory().ContinueWith(_ =&gt; _tasks.TryRemove(taskId, out var _)));
            return (task as Task&lt;T&gt;) ??
                throw new Exception($"Task with id {taskId} already exists but it has a different type {task.GetType()}. {typeof(Task&lt;T&gt;)} was expected");
        }
    }




I would like to add: I like the level of detail in the exception message. That should be very helpful in tracking down bugs if it is thrown and logged.