June 6, 2006

Boxing with C#

Theres nothing like learning by trying. Here is some code that I wrote that explicitly demonstrates boxing. I found in MSDN a little boxing test so I copied the balls of it (hope thats not illegal or anything) to here. The original article can be found through a quick google search. It is a good article on boxing.

June 4, 2006

Thread Pattern Starter Class

Background thread class as a starter for a threading class.


class WorkerThread
{

    public WorkerThread()
    {
        StartThread();
    }

    ~WorkerThread()
    {
        Dispose(false);
    }

    #region IDisposable Members

    private bool m_disposed = false;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!m_disposed)
        {
            if (disposing)
            {
                // Dispose managed resources
            }

            // Dispose unmanaged resources
            EndThread();
        }
        m_disposed = true;
    }

    #endregion



    #region Private Threading Related

    /// <summary>
    /// Actual threa object
    /// </summary>
    private Thread m_Thread = null;

    /// <summary>
    /// Give the thread a meaningful threadId
    /// </summary>
    private string threadId = "MyThreadName";

    /// <summary>
    /// Time to wait for the thread to finish 
    /// when merging the thread  
    /// back to the  main thread
    /// </summary>
    private uint waitForEndThread = 5000; // 5 seconds

    /// <summary>
    /// How long to pause for at the end of each iteration 
    /// </summary>
    private int m_ThreadSleepPeriod = 200;

    /// <summary>
    /// We use the m_PauseEvent to control the sleep period 
    /// of the thread. The m_PauseEvent
    /// sleeps for the given period  but we can force it to 
    /// wake up early by calling  
    /// Set on it.
    /// </summary>
    private AutoResetEvent m_PauseEvent = new AutoResetEvent(false);

    /// <summary>
    /// This does not need special protected access.
    /// It is set to false before the thread is  
    /// started  and  can  only get set to  true when 
    /// the  thread thread has begun.
    /// </summary>
    private bool m_Stop = false;

    /// <summary>
    /// Start the thread running
    /// </summary>
    private void StartThread()
    {
        if (m_Thread != null)
        {
            EndThread();
        }

        if (m_Thread == null)
        {
            if (m_PauseEvent == null)
            {
                m_PauseEvent = new AutoResetEvent(false);
            }
            m_Stop = false;
            m_Thread = new Thread(new ThreadStart(
this.ThreadRoutine)); m_Thread.IsBackground = true; m_Thread.Start(); m_Thread.Name = threadId; Thread.Sleep(0); } } /// <summary> /// EndThread to the thread to terminate it /// </summary> private void EndThread() { m_Stop = true; if (m_Thread != null) { if (m_PauseEvent != null) { m_PauseEvent.Set(); } try { if (m_Thread.IsAlive) { System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): EndThreading this thread \'"+
m_Thread.Name + "\' to \'" + Thread.CurrentThread.Name + "\'"); // Wait X seconds for the thread to finish if (!m_Thread.Join((int)waitForEndThread)) { System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): EndThread() failed, so ABORTing thread\'" +
m_Thread.Name + "\'"); m_Thread.Abort(); // otherwise abort } else { System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): EndThread() succeeded, Thread \'"+
m_Thread.Name + "\' is terminated"); } } else { System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): Thread \'" +
m_Thread.Name + "\' is not 'Alive' so EndThread() not invoked"); } } catch (System.Threading.ThreadStateException ex) { // Swallow any ThreadStateExceptions System.Diagnostics.Debug.WriteLine(
"WorkerThread.EndThread(): ThreadStateException caught in thread \'" +
m_Thread.Name + "\'" + ex.ToString()); } m_Thread = null; if (m_PauseEvent != null) { m_PauseEvent.Close(); m_PauseEvent = null; } } } /// <summary> /// The routine executed within the new thread /// </summary> private void ThreadRoutine() { string thrdName = m_Thread.Name; System.Diagnostics.Debug.WriteLine("Thread \'" +
thrdName + "\' thread routine is started"); try { while (m_Stop != true) { ThreadWork(); if ((m_Stop != true) && (m_ThreadSleepPeriod >= 0)) { m_PauseEvent.WaitOne(m_ThreadSleepPeriod,
false); } } } catch (Exception ex) { m_Stop = true; //if (log != null) System.Diagnostics.Debug.WriteLine(
"FATAL exception caught in thread routine \'" +
thrdName.ToString() + "\' Thread will be terminated" + ex.ToString()); } System.Diagnostics.Debug.WriteLine("Thread \'" + thrdName +
"\' end of thread routine reached"); } private void ThreadWork() { // Do something } #endregion }

Windows Service Pattern

Use this template as an example for creating a service.
Note that XXX is the service implementation class, this class just integrates that service object into windows services.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Runtime.Remoting;

using Logging = log4net;

namespace XXX.service
{
  /// <summary>
  /// Main service class as created by the code generator.
  /// </summary>
  public class XXXService 
  {
    #region Logging

    private static readonly Logging.ILog log =   
        Logging.LogManager.GetLogger(typeof(XXXService));

    #endregion Logging

    /// <summary>
    /// 
    /// </summary>
    public static readonly string ServiceDisplayName =
        "XXXService";

    #region Private Fields

    /// <summary> 
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components
        = null;

    /// <summary>
    /// Did the service start up successfully
    /// </summary>
    private bool startSuccesful = false;

    #endregion Private Fields

    #region Constructor

    /// <summary>
    /// XXXService constructor.
    /// </summary>
    public XXXService()
    {
      // This call is required by the Windows.Forms
      // Component Designer.
      InitializeComponent();
    }

    #endregion Constructor

    #region Main/Initialise

    // The main entry point for the process
    static void Main()
    {
      System.ServiceProcess.ServiceBase[] ServicesToRun;
  
      // More than one user Service may run within the
      // same process. To add another service to this 
      // process, change the following line to
      // create a second service object. For example,
      //
      //   ServicesToRun = new
      //    System.ServiceProcess.ServiceBase[] { 
      //        new XXXService(),
      //        new MySecondUserService() };
      //
      ServicesToRun = new System.ServiceProcess.ServiceBase[] 
        { new XXXService() };

      System.ServiceProcess.ServiceBase.Run(ServicesToRun);
    }

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      components = new System.ComponentModel.Container();
      this.ServiceName = ServiceDisplayName;
    }

    #endregion  Main/Initialise

    #region IDispose Implementation

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if (components != null) 
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

    #endregion IDispose Implementation

    #region Service Methods

    private bool IsDebugParameter(string arg)
    {
      var param = arg.ToUpperInvariant();

      return (param == "-DEBUG") || (param == "/DEBUG");
    }

    /// <summary>
    /// Set things in motion so your service can do its work.
    /// </summary>
    protected override void OnStart(string[] args)
    {
      // Allow us to be run in a debugger - for
      // development time support.
      if ((args.Length == 1) && IsDebugParameter(args[0]))
        Debugger.Launch();

      startSuccesful = false;
      string fileName = string.Empty;
      try
      { 
        log.Info("OnStart: Starting \'" + ServiceDisplayName<br> + "\'");

        System.IO.FileInfo fi = new System.IO.FileInfo(
            System.Windows.Forms.Application.ExecutablePath);
        System.Environment.CurrentDirectory = 
            fi.Directory.ToString();
        log.Info("Setting current directory to " 
            + System.Environment.CurrentDirectory);
        fileName = System.Windows.Forms.Application.ExecutablePath 
            + ".config";
        log.Info("Loading configuration from " + fileName);
        
        // If you have a remoting object that is 
        // initialised within the Config file       
        // initialise it here.
        // RemotingConfiguration.Configure(fileName);
            
        // Initialise 
        log.Info("OnStart: About to create XXX.");
        
        XXX xxx = new XXX(); // Service implementation class
        xxx.Initialise();
        
        // We assume that if the XXX is not constructed and 
        // initialised correctly it will throw an exception.
        // If we get to this point without an exception 
        // being thrown we assume 'alles ist gut'
        startSuccesful = true; 
        log.Info("OnStart: Started \'" + ServiceDisplayName 
            + "\' successfully=" + startSuccesful.ToString());
      }
      catch(Exception ex)
      {
        string errorMsg = 
          "Exception occured while starting service\'" 
            + ServiceDisplayName 
            + "\'. Expect an error message dialog");
        log.Fatal(errorMsg, ex);
        throw; // Results in error message: "XXX 
        // service on Local Computer started and 
        // then stopped. Some services stop if they 
        // have no work to do, for example, the 
        // Performance Logs and Alert service        
      }   
      if (startSuccesful)
      {
        // Tell the rest of the world we are running.
        ... 
      }
    }
 
    /// <summary>
    /// Stop this service.
    /// </summary>
    protected override void OnStop()
    {
      log.Info("OnStop: Stopping \'" + ServiceDisplayName<br> + "\'");
      
      if (xxx != null)
      {
        xxx.Dispose(); 
        ... 
      }
      
      if (startSuccesful)
      {
        // 
      }
      log.Info("OnStop: Stopped \'" + ServiceDisplayName<br> + "\'");
    }

    #endregion Service Methods

  }