Implementare un ThreadContext

L'idea è quella di avere un contesto a livello di Thread in modo da poter avere una bag di oggetti da potervi salvare... un pò come il contesto HTTP che viene associato ad ogni richiesta quando si opera sul web. La soluzione si basa sull'uso dei DataSlot allocabili a livello di Thread, per maggiori informazioni rimando Thread.AllocateNamedDataSlot. E' un idea in fase di studio, usare con cautela ;-p

[Program.cs]

using System;
using System.Threading;
using System.Runtime.Remoting.Contexts;
namespace ThreadTest
{
 class Program
 {

  #region ThreadCounter
  class ThreadCounter
  {
   public static ThreadCounter Current
   {
    get
    {
     ThreadCounter current = (ThreadCounter)ThreadContext.Current["ThreadCounter"];
     if(current == null)
     {
      current = new ThreadCounter();
      ThreadContext.Current["ThreadCounter"] = current;
     }
     return current;
    }
   }

   private int count;
   public int Count
   {
    get{return count;}
   }

   public void Increase()
   {
    count++;
   }
  }
  #endregion

  [STAThread]
  static void Main(string[] args)
  {   
   Console.WriteLine("(main): {0}",  ThreadCounter.Current.Count);
   for(int i = 0; i < 10; i++)
   {
    (new Thread(new ThreadStart(TestThreadContext))).Start();

    //Uso le sleep per fare in modo che i Thread 
    //si possano accavallare favorendo eventuali confitti.
    Thread.Sleep(1000); 
   }
   
   Console.WriteLine("(main): {0}", ThreadCounter.Current.Count);
   Console.ReadLine();
  }

  public static void TestThreadContext()
  {            
   Console.WriteLine("{0}: {1}", AppDomain.GetCurrentThreadId(), ThreadCounter.Current.Count);
   ThreadCounter.Current.Increase();   

   //Uso le sleep per fare in modo che i Thread 
   //si possano accavallare favorendo eventuali confitti.
   Thread.Sleep(2000);
   Console.WriteLine("{0}: {1}", AppDomain.GetCurrentThreadId(), ThreadCounter.Current.Count);
  }
 }
}

[ThreadContext.cs]

using System;
using System.Collections;
using System.Threading;

namespace ThreadTest
{

 /// Define a thread context class. The instance of context is linked with current thread 
 /// allocating a named data slot.
 public class ThreadContext: DictionaryBase 
 {
  //static fields definition
  static readonly string  THREAD_CTX_SLOT_NAME = Guid.NewGuid().ToString();
  static LocalDataStoreSlot localDataStoreSlot;

  //static constructor
  static ThreadContext()
  {
   //Allocates a named data slot on all threads.
   localDataStoreSlot = Thread.AllocateNamedDataSlot(THREAD_CTX_SLOT_NAME);   
  }

  /// Retrieve current ThreadContext.
  public static ThreadContext Current
  {
   get
   {
    ThreadContext ctx = (ThreadContext)Thread.GetData(localDataStoreSlot);    
    if(ctx == null)
    {     
     ctx = new ThreadContext();
     Thread.SetData(localDataStoreSlot, ctx);      
    }
    return ctx;
   }
  }

  #region DictionaryBase string/object methods
  // Sample implementation of string/object dictionary.
  
  public object this[ string key ]  
  {
   get  
   {
    return Dictionary[key];
   }
   set  
   {
    Dictionary[key] = value;
   }
  }

  public ICollection Keys  
  {
   get  
   {
    return( Dictionary.Keys );
   }
  }

  public ICollection Values  
  {
   get  
   {
    return( Dictionary.Values );
   }
  }

  public void Add( string key, object value )  
  {
   Dictionary.Add( key, value );
  }

  public bool Contains( string key )  
  {
   return( Dictionary.Contains( key ) );
  }

  public void Remove( string key )  
  {
   Dictionary.Remove( key );
  }

  protected override void OnInsert( object key, object value )  
  {
   if ( !(key is string) )
    throw new ArgumentException( "key must be of type String.", "key" );  
  }

  protected override void OnRemove( object key, object value )  
  {
   if ( !(key is string) )
    throw new ArgumentException( "key must be of type String.", "key" );  
  }

  protected override void OnSet( object key, object oldValue, object newValue )  
  {
   if ( !(key is string) )
    throw new ArgumentException( "key must be of type String.", "key" ); 
  }

  protected override void OnValidate( object key, object value )  
  {
   if ( !(key is string) )
    throw new ArgumentException( "key must be of type String.", "key" );   
  }
  #endregion
 }
}

posted @ martedì 6 settembre 2005 01:51

Print
Comments have been closed on this topic.
«aprile»
domlunmarmergiovensab
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011