title: Create a context group in C# to bind several operations into one
body: <p>I need to spawn individual actions that are not aware of each other but can be grouped into something like an execution group. The individual actions are also cascaded so that there is also more than one hierarchy level.</p>
  
  <p>I can only show a small example to make things a bit clearer and open this example as a starting point for discussions.The example does not make complete sense, but it is to show what my intentions are.</p>
  
  <p>In the example I want to start several algorithms that spawn other algorithms. Before I encapsulate the algorithms in an some sort of a context that binds all algorithms that were allocated in this context and adds them to the list of this context. At a certain time it could happen that someone wants to terminate all algorithms the Terminate() method can be called which calls the Termimnate() method on all algorithms in that context. Of course to make this work the algorithms need knowledge of the AlgorithmContext structure.</p>
  
  <p>Another question is how do I transport the AlgorithmContext to the next thread or task? It also need to be threadsafe.</p>
  
  <p>In the case of this example you can argue that I could hand over the CancellationToken down in the hierarchy of the algorithms but please keep in mind this is only an example. If was thinking in the direction of an ExecutionContext but maybe there are better approaches?</p>
  
  <pre><code>public class Algorithm
  {
      public readonly AlgorithmContext Context;
      public Algorithm()
      {
          Context = AlgorithmContext.Current;
      }
  
      public void Terminate() { }
  }
  
  public class SmoothImage : Algorithm { }
  public class SharpenImage : Algorithm { }
  
  public class Example
  {
      public void Process(float[] imagedata)
      {
          // Everyone below should see the AlgorithmContext.Current until the end of the using.
          // No one shall be able to interfere the Current inside the braces for example if another
          // thread creates another instance of AlgorithmContext.
          var Task1 = Task.Run(() =&gt;
          {
              // The AlgorithmContext.Current shall be Context 1 until the end of the using braces.
              using (var ctx = new AlgorithmContext("Context 1"))
              {
                  CancellationTokenSource ct = new CancellationTokenSource();
                  ct.Token.Register(() =&gt; ctx.Terminate());
  
                  SmoothImage smoothImage = new SmoothImage();
                  SharpenImage sharpenImage = new SharpenImage();
              }
          });
  
  
          var Task2 = Task.Run(() =&gt;
          {
              // The AlgorithmContext.Current shall be Context 2 until the end of the using braces.
              using (var ctx = new AlgorithmContext("Context 2"))
              {
                  CancellationTokenSource ct = new CancellationTokenSource();
                  ct.Token.Register(() =&gt; ctx.Terminate());
  
                  SmoothImage smoothImage = new SmoothImage();
                  SharpenImage sharpenImage = new SharpenImage();
              }
          });
  
          var Task3 = Task.Run(() =&gt;
          {
              // The AlgorithmContext.Current shall be Context 2 until the end of the using braces.
              using (var ctx = new AlgorithmContext("Context 3"))
              {
                  var Task4 = Task.Run(() =&gt;
                      {
                          // The AlgorithmContext.Current shall be Context 3 
                          CancellationTokenSource ct = new CancellationTokenSource();
                          ct.Token.Register(() =&gt; ctx.Terminate());
  
                          SmoothImage smoothImage = new SmoothImage();
                          SharpenImage sharpenImage = new SharpenImage();
                      });
              }
          });
  
  
          // There is no current context outside here at all times.
          Task.WaitAll(Task1, Task2, Task3);
      }
  }
  
  public class AlgorithmContext : IDisposable
  {
      List&lt;Algorithm&gt; Algorithms = new List&lt;Algorithm&gt;();
      public readonly string Name;
  
      [ThreadStatic]
      public static AlgorithmContext Current;
  
      public AlgorithmContext(string name)
      {
          Name = name;
          Current = this;
      }
  
      public void Add(Algorithm algorithm) { Algorithms.Add(algorithm); }
  
      public void Terminate()
      {
          foreach (var algo in Algorithms) algo.Terminate();
          Algorithms.Clear();
      }
  
      public void Dispose()
      {
          Current = null;
      }
  }
  </code></pre>