Friday, March 26, 2010

Code: C# Simple Multithreading Example using ThreadPool

Below you will find a simple, complete code sample for multithreading in C# using the ThreadPool class.  This sample uses a simple counter to track the number of threads that are active to prevent the application from closing before all threads have completed.  Although there are other ways to force a method to wait for all threads to complete before exiting, using a static counter allows you to create a separate method to determine when the application is allowed to exit.  This is useful for handling OnStop events on windows services.  Within the StopProcessing() method you could also set a flag that would prevent your application from creating new threads.

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6.  
  7. namespace MultiThreadedApp
  8. {
  9.     class Program
  10.     {
  11.         static int _threadCounter = 0;
  12.  
  13.         static void Main(string[] args)
  14.         {
  15.             for (int i = 0; i < 10; i++)
  16.             {
  17.                 CreateThread(i);
  18.             }
  19.  
  20.             StopProcessing();
  21.  
  22.             Console.WriteLine("Finished");
  23.         }
  24.  
  25.         private static void CreateThread(int threadId)
  26.         {
  27.             Console.WriteLine("Creating Thread {0}", threadId);
  28.             MethodParameters newParameter = new MethodParameters();
  29.             newParameter.ThreadId = threadId;
  30.             newParameter.ThreadCreated = DateTime.Now;
  31.             Interlocked.Increment(ref _threadCounter);
  32.             ThreadPool.QueueUserWorkItem(new WaitCallback(LongRunningProcess), (object)newParameter);
  33.         }
  34.  
  35.         private static void LongRunningProcess(object input)
  36.         {
  37.             MethodParameters inputParams = (MethodParameters)input;
  38.             Random random = new Random(((MethodParameters)input).ThreadId);
  39.             Thread.Sleep(random.Next(500, 5000));
  40.             Console.WriteLine("Thread {0} complete in {1} seconds", inputParams.ThreadId,
  41.                 (DateTime.Now - inputParams.ThreadCreated).TotalSeconds);
  42.  
  43.             Interlocked.Decrement(ref _threadCounter);
  44.         }
  45.  
  46.         private static void StopProcessing()
  47.         {
  48.             Console.WriteLine("Waiting for {0} threads to complete", _threadCounter);
  49.             while (_threadCounter > 0)
  50.                 Thread.Sleep(500);
  51.         }
  52.  
  53.         private class MethodParameters
  54.         {
  55.             public DateTime ThreadCreated { get; set; }
  56.             public int ThreadId { get; set; }
  57.         }
  58.     }
  59. }

Tuesday, March 23, 2010

Tech: HTPC build

I built a home theater PC recently using parts from Newegg and running Windows 7 media center.  I’ve been pretty happy with it so far, watching Netflix, Hulu, DVD’s, and home videos has worked out well.  There are however a couple issues I’ve noticed:

1.  I had to uninstall the Realtek audio drivers to get the HDMI audio to work.
2.  The HDMI video connection to my television doesn’t always work.  Sometimes I have to restart the computer or put it to sleep for the connection to be made.  It seems to work best if I turn the television on and set it to the correct input before turning on the computer.  I haven’t read any other reviewers having this issue, so it might be an issue with my Panasonic plasma.
3.  There is about a 1/2 inch black border on the outside of the television.  This isn’t all that surprising, however I did expect the ATI catalyst control center to allow me to correct the overscan.  This really is not noticeable though, and doesn’t bother me too much.

Here are the parts I used:
Motherboard: GIGABYTE GA-MA785GM-US2H
CPU: AMD Athlon II X2 240 Regor 2.8GHz Socket AM3 65W Dual-Core Processor
RAM: G.SKILL 2GB (2 x 1GB) 240-Pin DDR2 SDRAM DDR2 800 (PC2 6400)
Hard Drive: Western Digital Caviar Blue WD5000AAKS 500GB 7200 RPM SATA 3.0Gb/s 3.5
DVD: Sony Optiarc 24X DVD/CD Rewritable Drive Black SATA Model AD-7240S-0B
Case: hec Black 0.7mm Thickness SECC 7K09 Micro ATX Media Center / HTPC Case

The total cost for the system was $325.  I had access to Windows 7 via my TechNet subscription so that saved me an extra $200.  This was my first build using a micro-ATX motherboard and case, it was a tight fit getting all of the pieces in the case.  I also had to use an IDE to SATA power adapter I had, the power supply only had one SATA power connector.

Monday, March 15, 2010

Code: C# Best Practices

I found a nice C# coding best practices doc from DotNetSpider today: http://www.dotnetspider.com/tutorials/BestPractices.aspx

Great to use as a starting point for your own standards.

A couple things I’d change:

1.  There should only be 1 exit point in a method.  The word return should only appear once, and it should be the last line in the method.

2.  The Public regions should appear before Private regions in a class.  When navigating to a business method from a UI class it seems more natural to jump into the top of a file and work your way down.

Friday, March 12, 2010

Code: How To Run a .Net Windows Service as a Console Application

Attempting to debug a windows service can be a nightmare, especially if you are trying to debug the OnStart event by attaching to a local process.  To get around this you can configure the windows service to launch as a console application.  To do this go to the property pages of your service and select the Application tab.  Change the output type to Console Application:

image

Next modify the program.cs file by adding an args input parameter to the Main method and surrounding the logic in the method with an if statement like so:

Code Snippet
  1. static void Main(string[] args)
  2. {
  3.     if (args.Length == 0)
  4.     {
  5.         ServiceBase[] ServicesToRun;
  6.         ServicesToRun = new ServiceBase[]
  7.         {
  8.         new Service1()
  9.         };
  10.         ServiceBase.Run(ServicesToRun);
  11.     }
  12.     else
  13.     {
  14.         //DoWork();
  15.     }
  16. }

Now modify your service1.cs file to call the same worker method on start:

Code Snippet
  1. public partial class Service1 : ServiceBase
  2. {
  3.     public Service1()
  4.     {
  5.         InitializeComponent();
  6.     }
  7.  
  8.     protected override void OnStart(string[] args)
  9.     {
  10.         //DoWork();
  11.     }
  12.  
  13.     protected override void OnStop()
  14.     {
  15.     }
  16. }

Finally go to the Debug tab on the property pages and add a word to the Command line arguments text box:

image

Now just start debugging and your breakpoint will be hit!

image

Wednesday, March 3, 2010

Tech: One box to rule them all

I have home movies, I have downloaded movies, I subscribe to Netflix, I watch Hulu, and I have Dish Network with DVR service.  I want to do all of this on my Panasonic TV, why can’t one box handle all of this content?  Currently I’ve got my system down to two boxes with my new HTPC build and Dish Network DVR box.  How awesome would it be if those two boxes were combined?  Windows Media Center would support this if Dish Network would create (or allow the Windows team to) a PCI satellite card and WMC plug in.  Alternatively it could be accomplished for free with Boxee.  That box would sell like hotcakes.  It appears that DirecTV is partnering with Tivo again with Tivo’s new DVR service with online content support, but local content is still left out of the picture.

Why can’t cable/satellite providers realize this is what people want and partner up with hardware/software vendors to make it happen?  The first company to accomplish this would get a very strategic lead on the competition.

Code: An attempt was made to load a program with an incorrect format.

I received the following error message today when setting up a website in IIS 7 (on Windows 7):

Could not load file or assembly X or one of its dependencies. An attempt was made to load a program with an incorrect format.

This error was due to a 32 bit website on a 64 bit system.  To fix this you need to go to the Advanced Settings on the Application pool and set “Enable 32-Bit Applications” to True.

image

Tech: How To Permanently Set a Program To Run as Administrator

I got tired of right clicking notepad to run as administrator to edit my hosts file, and figured there had to be a way to make it always run as administrator. 

Right click on the program in the start menu and select Properties->Advanced check “Run as Administrator”. 

image