Mar 21 2010

Hybrid Cryptosystem

Category: CryptographyMike Lovell @ 12:11 pm

When using ‘asymmetric’ (public-private key) encryption, there are a few limitations:

  • Slow Speed - Symmetric (key) encryption is far quicker
  • Single Recipient – You can only encrypt to a single public key

However we can combine ‘asymmetric’ and ’symmetric’ cryposystems to create a hybrid system which will allow us to harness the speed of ‘symmetric’encryption and allow multiple recipients by simply encrypting the shared ‘symmetric key’ to each public ‘asymmetric key’ we want to use.

So lets create a simple format for a ‘hybrid cryptosystem‘.  We’re going to be using ‘RSA‘ for our ‘asymmetric encryption‘, and AES (Rijndael) for our ‘symmetric encryption‘.


1 Byte    Recepient count: 1-255 recepients allowed
4 Bytes   Recepient 1 data: Size (Int32)
20 Bytes  Recepient 1 data: SHA1 hash of public key
n Bytes   Recepient 1 data: Shared key/password (encrypted to public key)
...
4 Bytes   Recepient n data: Size (Int32)
20 Bytes  Recepient n data: SHA1 hash of public key
n Bytes   Recepient n data: Shared key/password (encrypted to public key)

n Bytes   Encrypted data: Encrypted using AES (Rijndael) and shared key/password

 

Now we have our format defined, we can implement a simple C# application that follows this.  First we’re going to implement a ‘CryptoProvider‘ class.  This is going to handle both ‘asymmetric‘ and ‘symmetric‘ encryption and decryption, key generation, hash generation and random byte generation.  Our key/password is going to be randomly generated and 48 bytes long.  The first 16 will be the ‘IV‘ vector, the last 32 will be the ‘key‘.

   1:  // Author: Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  class CryptoProvider
   4:  {
   5:      private    RSACryptoServiceProvider    rsaProvider;
   6:   
   7:   
   8:      public CryptoProvider(int keySize)
   9:      {
  10:          rsaProvider = new RSACryptoServiceProvider(keySize);    // Generate new key
  11:      }
  12:   
  13:   
  14:      public CryptoProvider(string xmlKey)
  15:      {
  16:          rsaProvider = new RSACryptoServiceProvider();
  17:   
  18:          rsaProvider.FromXmlString(xmlKey);    // Import XML Key
  19:      }
  20:   
  21:   
  22:      public string ToXmlString(bool includePrivateKey)
  23:      {
  24:          return rsaProvider.ToXmlString(includePrivateKey);    // Export XML Key
  25:      }
  26:   
  27:   
  28:      public byte[] Hash()
  29:      {
  30:          var sha1 = new SHA1Managed();
  31:   
  32:          // Hash from the modulus
  33:          return sha1.ComputeHash(rsaProvider.ExportParameters(false).Modulus);
  34:      }
  35:   
  36:   
  37:      public byte[] Encrypt(byte[] data)
  38:      {
  39:          return rsaProvider.Encrypt(data, false);
  40:      }
  41:   
  42:   
  43:      public byte[] Decrypt(byte[] data)
  44:      {
  45:          return rsaProvider.Decrypt(data, false);
  46:      }
  47:   
  48:   
  49:      public static byte[] RandomSequence(int size)
  50:      {
  51:          var random        = new byte[size];
  52:          var rngProvider    = new RNGCryptoServiceProvider();
  53:  
  54:          rngProvider.GetBytes(random);
  55:   
  56:          return random;
  57:      }
  58:   
  59:   
  60:      public static byte[] Encrypt(byte[] data, byte[] password)
  61:      {
  62:          var rijndael    = Rijndael.Create();
  63:   
  64:          rijndael.KeySize    = 256;    // Maximum key size
  65:          rijndael.IV            = SubBytes(password, 0, 16);    // First 16 bytes is vector
  66:          rijndael.Key        = TrimBytes(SubBytes(password, 16, password.Length - 16), 32);    // Last 32 is key
  67:          rijndael.Mode        = CipherMode.CBC;
  68:   
  69:          var stream            = new MemoryStream();
  70:          var cryptoStream    = new CryptoStream(stream, rijndael.CreateEncryptor(), CryptoStreamMode.Write);
  71:   
  72:          cryptoStream.Write(data, 0, data.Length);
  73:          cryptoStream.FlushFinalBlock();
  74:   
  75:          cryptoStream.Close();
  76:   
  77:          var encryptedData = stream.ToArray();
  78:   
  79:          stream.Close();
  80:   
  81:          return encryptedData;
  82:      }
  83:   
  84:   
  85:      public static byte[] Decrypt(byte[] data, byte[] password)
  86:      {
  87:          var rijndael    = Rijndael.Create();
  88:   
  89:          rijndael.KeySize    = 256;    // Maximum key size
  90:          rijndael.IV            = SubBytes(password, 0, 16);    // First 16 bytes is vector
  91:          rijndael.Key        = TrimBytes(SubBytes(password, 16, password.Length - 16), 32);    // Last 32 is key
  92:          rijndael.Mode        = CipherMode.CBC;
  93:   
  94:          var stream            = new MemoryStream(data);
  95:          var cryptoStream    = new CryptoStream(stream, rijndael.CreateDecryptor(), CryptoStreamMode.Read);
  96:   
  97:          var    length            = cryptoStream.Read(data, 0, data.Length);
  98:          var    decryptedData    = new byte[length];
  99:   
 100:          stream.Read(decryptedData, 0, length);
 101:   
 102:          cryptoStream.Close();
 103:          stream.Close();
 104:   
 105:          Buffer.BlockCopy(data, 0, decryptedData, 0, length);
 106:   
 107:          return decryptedData;
 108:      }
 109:   
 110:   
 111:      public byte[] DecryptPasswordAndData(byte[] data)
 112:      {
 113:          var    buffer            = new MemoryStream(data);
 114:          var    keyCount        = buffer.ReadByte();    // First byte is key count
 115:          var    thisHash        = Convert.ToBase64String(this.Hash());
 116:          var    password        = (byte[])null;
 117:   
 118:          if (keyCount < 1) throw new Exception("No keys found");
 119:  
 120:          var    keyLengthBuffer    = new byte[4];
 121:  
 122:          for (int i=0; i < keyCount; i++)
 123:          {
 124:              // First 4 bytes are Int32 of encrypted hash/password size
 125:              buffer.Read(keyLengthBuffer, 0, 4);
 126:   
 127:              var    keyLength    = BitConverter.ToInt32(keyLengthBuffer, 0);
 128:              var    keyHash        = new byte[20];    // First 20 bytes is SHA1 hash
 129:              var    keyPassword    = new byte[keyLength - 20];    // Remaining byes are encrypted password
 130:   
 131:              buffer.Read(keyHash, 0, 20);    // Read first 20 bytes (SHA1 Hash)
 132:              buffer.Read(keyPassword, 0, keyPassword.Length);    // Read remaining bytes (password)
 133:   
 134:              if (Convert.ToBase64String(keyHash) == thisHash)
 135:              {
 136:                  password = Decrypt(keyPassword);    // Decrypt password
 137:              }
 138:          }
 139:   
 140:          if (password == null) throw new Exception("Data not encrypted to your key");
 141:   
 142:          // remaining bytes are encrypted data
 143:          var encryptedData     = new byte[buffer.Length - buffer.Position];
 144:   
 145:          // Read remaining bytes
 146:          buffer.Read(encryptedData, 0, encryptedData.Length);
 147:   
 148:          buffer.Close();
 149:   
 150:          return CryptoProvider.Decrypt(encryptedData, password);    // Decrypt data
 151:      }
 152:   
 153:   
 154:      private static byte[] SubBytes(byte[] source, int offset, int length)
 155:      {
 156:          var    subData    = new byte[length - offset];
 157:   
 158:          Buffer.BlockCopy(source, offset, subData, 0, length - offset);
 159:   
 160:          return subData;
 161:      }
 162:   
 163:   
 164:      private static byte[] TrimBytes(byte[] source, int maxLength)
 165:      {
 166:          if (source.Length > maxLength)
 167:          {
 168:              var trimmedData = new byte[maxLength];
 169:   
 170:              Buffer.BlockCopy(source, 0, trimmedData, 0, maxLength);
 171:   
 172:              return trimmedData;
 173:          }
 174:   
 175:          return source;
 176:      }
 177:  }
 178:   

Then lets create a collection of ‘CryptoProvider‘ which will allow us to encrypt our data to multiple public keys.

 179:   
 180:  class CryptoProviderCollection : List<CryptoProvider>
 181:  {
 182:      public byte[] EncryptPasswordAndData(byte[] data)
 183:      {
 184:          if (this.Count < 1 || this.Count > 255) throw new Exception("Too few or too many recepients");
 185:   
 186:          var password    = CryptoProvider.RandomSequence(16 + 32);    // Random password
 187:                                                                      // First 16 = Vector
 188:                                                                      // Last 32 = Key
 189:          var stream        = new MemoryStream();
 190:  
 191:          stream.WriteByte((byte)this.Count); // First byte is recepient count
 192:   
 193:          var encryptedPasswords    =
 194:              (
 195:                  from    item
 196:                  in        this
 197:                  select    CombineBytes
 198:                      (
 199:                          item.Hash(),            // Public key hash
 200:                          item.Encrypt(password)    // Password encrypted for recipient
 201:                      )
 202:              );
 203:   
 204:   
 205:          foreach (var encryptedPassword in encryptedPasswords)
 206:          {    // For each recepient
 207:   
 208:              // Store encrypted password length as Int32 (first 4 bytes)
 209:              stream.Write(BitConverter.GetBytes(encryptedPassword.Length), 0, 4);
 210:              // Store encrypted password
 211:              stream.Write(encryptedPassword, 0,  encryptedPassword.Length);
 212:          }
 213:   
 214:          var encryptedData = CryptoProvider.Encrypt(data, password);    // Encrypt data
 215:   
 216:          stream.Write(encryptedData, 0, encryptedData.Length);        // Store
 217:   
 218:          var encryptedBytes = stream.ToArray();
 219:   
 220:          stream.Close();
 221:   
 222:          return encryptedBytes;
 223:      }
 224:   
 225:   
 226:      private byte[] CombineBytes(byte[] dataA, byte[] dataB)
 227:      {
 228:          var combinedData = new byte[dataA.Length + dataB.Length];
 229:   
 230:          Buffer.BlockCopy(dataA, 0, combinedData, 0, dataA.Length);
 231:          Buffer.BlockCopy(dataB, 0, combinedData, dataA.Length, dataB.Length);
 232:   
 233:          return combinedData;
 234:      }
 235:  }
 236:   

Now lets see if it works.  We’ll create 3 ‘RSA‘ keys then encrypt the data for the first two recipients ONLY, just to see if the 3rd cannot decrypt the data (which should be the case).

 237:   
 238:  class Program
 239:  {
 240:      static void Main(string[] args)
 241:      {
 242:          var    key1    = new CryptoProvider(1024);    // Make a new key
 243:          var    key2    = new CryptoProvider(2048);    // ..
 244:          var    key3    = new CryptoProvider(1024);    // ..
 245:   
 246:          var col    = new CryptoProviderCollection();
 247:  
 248:          col.Add(key1);    // Add only key1 and key2
 249:          col.Add(key2);    // to the collection
 250:   
 251:          // Encrypt data and random password for key1 and key2
 252:          var encryptedData    = col.EncryptPasswordAndData(Encoding.UTF8.GetBytes("Test Encrypted Data"));
 253:  
 254:          // Decrypt using key1
 255:          Console.WriteLine(Encoding.UTF8.GetString(key1.DecryptPasswordAndData(encryptedData)));
 256:          // Decrypt using key2
 257:          Console.WriteLine(Encoding.UTF8.GetString(key2.DecryptPasswordAndData(encryptedData)));
 258:  
 259:          try
 260:          {
 261:              // Decrypt using key3, that we DIDN'T use for encryption, this will fail
 262:              Console.WriteLine(Encoding.UTF8.GetString(key3.DecryptPasswordAndData(encryptedData)));
 263:          }
 264:          catch (Exception e)
 265:          {
 266:              Console.WriteLine("ERROR: {0}",  e.Message.ToString());
 267:          }
 268:   
 269:          Console.ReadLine();
 270:      }
 271:  }

And the result you should see is the following:

Test Encrypted Data
Test Encrypted Data
ERROR: Data not encrypted to your key

You can expand the classes to carry out ‘exception handling‘, and build a robust ‘hybrid cryptosystem‘ from this basic implementation.

Download Visual Studio 2010 Project (8.33k)

Tags: , , , , , , , , , ,


One Response to “Hybrid Cryptosystem”

Leave a Reply

Mar 18 2010

Audible Ping

Category: Networking, SoundMike Lovell @ 8:32 pm

This is either the greatest or most annoying tool ever!  I have to reboot a lot of machines and I always kick of a continuous ping against them to see them go down and come up again.  I thought it would be great if I could make a hospital heart-monitor style beeping ping utility, so I did.  Here it is.

First lets write a ‘ToneHandler‘ class to control our sound.  We’ll give this the capability to either make a single ‘beep‘ or a continous tone (indicating the machine is down).  We’re going to use ‘Console.Beep‘ for this.  We’ll run our continuous tone function in its own thread so we can terminate it when the machine starts pinging again.

   1:  // Author Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  class ToneHandler
   4:  {
   5:      private    Thread    constantToneThread;
   6:   
   7:   
   8:      public void SingleTone(int frequency, int duration)
   9:      {
  10:          Console.Beep(frequency, duration);
  11:      }
  12:   
  13:   
  14:      public void ConstantToneBegin()
  15:      {
  16:          if (constantToneThread != null) return;    // If already making tone, exit
  17:   
  18:          constantToneThread    = new Thread(new ThreadStart(delegate()
  19:              {
  20:                  while (true)
  21:                  {    // Infinite loop, we'll kill it later
  22:                      Console.Beep(500, Int32.MaxValue);
  23:                  }
  24:              }));
  25:   
  26:          constantToneThread.IsBackground = true;
  27:          constantToneThread.Start();    // Kick it off
  28:      }
  29:   
  30:   
  31:      public void ConstantToneEnd()
  32:      {
  33:          if (constantToneThread == null) return;    // If already not making tone, exit
  34:   
  35:          Console.Beep(500, 1);    // Send another Beep, this will terminte the other one
  36:   
  37:          constantToneThread.Join(500);    // Terminate thread
  38:   
  39:          constantToneThread = null;
  40:   
  41:          return;
  42:      }
  43:  }
  44:   

Now lets make a little wrapper for the .NET ‘Ping‘ class.  Because we’re going to link the tone and duration of the tone to the round-trip time of the ping, all we want our ping class to return is the time the ping took, or ‘-1‘ if the ping failed.

  45:   
  46:  class PingWrapper
  47:  {
  48:      private    IPAddress    ipAddress;
  49:   
  50:      private    Ping        ping        = new Ping();
  51:      private    PingOptions    pingOptions    = new PingOptions();
  52:   
  53:      private    byte[]        buffer        = new byte[32]
  54:          {    // 32 byte buffer
  55:              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  56:              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  57:              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  58:              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  59:          };
  60:   
  61:      public PingWrapper(string host)
  62:      {
  63:          // Resolve the host once, not at every ping
  64:          ipAddress = Dns.GetHostAddresses(host)[0];
  65:   
  66:          pingOptions.DontFragment = true;
  67:      }
  68:   
  69:   
  70:      public int Send()
  71:      {
  72:          var reply = ping.Send(ipAddress, 1000, buffer, pingOptions);
  73:   
  74:          // Only send a ping every 1 second
  75:          Thread.Sleep(1000 - (int)reply.RoundtripTime);
  76:   
  77:          if (reply.Status == IPStatus.Success)
  78:          {
  79:              return (int)reply.RoundtripTime;
  80:          }
  81:          else
  82:          {
  83:              return -1;
  84:          }
  85:      }
  86:  }
  87:   

Now we’ll take the first argument of the command line and use it as the host we’re going to ping.  We’ll setup a continuous loop in a different thread (so we can terminate it from the main thread) and get it to call our tone class based on the output of ping.  We’ll also display a 1 character status of what happened (success ‘_‘ or failed ‘!‘)

  88:   
  89:  class Program
  90:  {
  91:      static void Main(string[] args)
  92:      {
  93:          if (args.Length != 1)
  94:          {
  95:              Console.WriteLine("Usage: gotinker.audibleping <hostname or IP>");
  96:              return;
  97:          }
  98:   
  99:          var    terminate    = false;
 100:          var    toneHandler = new ToneHandler();
 101:          var    ping        = new PingWrapper(args[0]);
 102:   
 103:          var loopThread    = new Thread(new ThreadStart(delegate()
 104:              {
 105:                  while (true)
 106:                  {
 107:                      if (terminate) break;
 108:   
 109:                      var result = ping.Send();
 110:   
 111:                      if (result == -1)
 112:                      {
 113:                          Console.Write("!");
 114:                          toneHandler.ConstantToneBegin();
 115:                      }
 116:                      else
 117:                      {
 118:                          Console.Write("_");
 119:                          toneHandler.ConstantToneEnd();
 120:                          toneHandler.SingleTone(500 - (result / 4), ((result * 4) + 100));
 121:                      }
 122:                  }
 123:              }));
 124:   
 125:          Console.WriteLine("(Press any enter to exit)");
 126:   
 127:          loopThread.Start();
 128:   
 129:          Console.ReadLine();
 130:   
 131:          terminate = true;    // Our loops checks for this to exit
 132:   
 133:          while (loopThread.ThreadState == ThreadState.Running)
 134:          {
 135:              Thread.Sleep(50);    // Wait fot the thread to terminate
 136:          }
 137:      }
 138:  }

And the result, here’s me pinging something while I reboot it (Download Audio of Demo):

(Press any enter to exit)
________!!!!!!_________!_____________

Download Visual Studio 2010 Project (7.16k)

Tags: , , , , , , , , , , , ,


One Response to “Audible Ping”

Leave a Reply

Mar 16 2010

Handling Unhandled Exceptions

Category: Events, Exception HandlingMike Lovell @ 7:34 pm

If an exception occurs outside a ‘try-catch block‘, it’s nice to have a way of either logging this, or having yourself notified.  The ‘EventLog‘ might be a way to go, but in the case of software running on your end-users PC, you might want to make it easy for them to send ‘unhandled exceptions‘ to you directly.  After all, if it’s complicated they may not have the technical expertise to get the information to you.  Something you might find easy might be beyond the reach of your end-users.

Here’s a quick example of both how to implement a ‘UnhandledException‘ EventHandler, and how to allow your end-user to easily email the information to you.

First lets make a little function that’s designed to fail!  This following function is going to always throw an Exception (divide by zero).

   1:  class Program
   2:  {
   3:      // Author Mike Lovell (mike.lovell@gotinker.com)
   4:   
   5:      private static int OtherFunction(int i)
   6:      {
   7:          var j = 0;
   8:   
   9:          return i / j;    // Divide by zero exception
  10:                          // will happen here
  11:      }
  12:   

Now the handler.  Inside ‘AppDomain.CurrentDomain‘ lives the ‘UnhandledException‘ event handler, this is fired when an exception is thrown (and of course, not handled!).  What we’re going to do is open up the end-users default mail client, with the ‘to‘, ‘subject‘ and ‘body‘ prefilled with the information we need.  In this case, we’re going to take the date, the full path and filename of the executable and the full exception (including stack trace).  Because we want the exception exactly as it would have appeared, and including any non-latin characters (their mail client may not support) we’ve Base64 encoded the UTF8 bytes of our exception string.

We can very easily reverse this process at the other end, to get to the exception.

  13:   
  14:      static void Main(string[] cargs)
  15:      {
  16:          AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs args)
  17:              {
  18:                  var exception = ((Exception)args.ExceptionObject);
  19:   
  20:                  var mailProcess = Process.Start
  21:                      (
  22:                          String.Format
  23:                              (
  24:                                  "mailto:null@gotinker.com?subject=Unhandled Exception ({0})&body={1}%0A{2}%0A%0A{3}",
  25:                                  HttpUtility.HtmlEncode(exception.Message),
  26:                                  DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss"),
  27:                                  Process.GetCurrentProcess().MainModule.FileName,
  28:                                  Convert.ToBase64String(Encoding.UTF8.GetBytes(exception.ToString())
  29:                              )
  30:                          )
  31:                      );
  32:              };

Now we want to call the function so we actually cause the exception to be thrown

  33:   
  34:          OtherFunction(123);
  35:      }
  36:  }

And the result?  Should look something like this:

GoTinker Exception Handler Email

Exception Handler Email

Download Visual Studio 2010 Project (6.78k)

Tags: , , , , , , ,


Leave a Reply

Mar 14 2010

Inheriting EventArgs for better events

Category: EventsMike Lovell @ 10:41 pm

In a lot of cases, you need to return some custom data from your events.  Inheriting from ‘EventArgs’ gives you the opportunity to do this.  Here’s an example of how you do it.  Fortunately this time, it’s all self explanatory.

   1:  // Author Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  class Firey
   4:  {
   5:      public class MyEventArgs : EventArgs
   6:      {
   7:          public    bool    IsSomethingNice;
   8:          public    int        SomeNumber;
   9:          public    string    SomeText;
  10:      }
  11:   
  12:   
  13:      public    event    EventHandler<MyEventArgs>    MyEvent;
  14:   
  15:   
  16:      public void FireEvent()
  17:      {
  18:          if (MyEvent != null) MyEvent(this, new MyEventArgs()
  19:              {
  20:                  IsSomethingNice    = true,
  21:                  SomeNumber        = 666,
  22:                  SomeText        = "Hello World"
  23:              });
  24:      }
  25:  }
  26:   
  27:   
  28:   
  29:  class Program
  30:  {
  31:      static void Main(string[] pargs)
  32:      {
  33:          var firey    = new Firey();
  34:   
  35:          firey.MyEvent += delegate(object sender, Firey.MyEventArgs args)
  36:              {
  37:                  Console.WriteLine
  38:                      (
  39:                          "Event Fired:\nIsSomethingNice: {0}\nSomeNumber: {1}\nSomeText: {2}",
  40:                          args.IsSomethingNice,
  41:                          args.SomeNumber,
  42:                          args.SomeText
  43:                      );
  44:              };
  45:   
  46:          firey.FireEvent();
  47:   
  48:          Console.ReadLine();
  49:      }
  50:  }

Download Visual Studio 2010 Project (6.35k)


Leave a Reply

Mar 13 2010

A simple custom thread queue

Category: ThreadingMike Lovell @ 8:05 pm

If you use the built-in ‘ThreadPool’, you lose a lot of control over the thread after you queue up your work.  Here’s an example of a custom thread queue.  You can add more work to it and adjust the maximum threads whilst it’s running, like the built-in ‘ThreadPool’But you can issue a ‘Stop’ and terminate all the currently running threads.  You can expand the classes to add even more functionality but I’ve just covered the basics.

As always, I’m going to handle all my ‘work’ using the ‘Action’ class.  I’ll be using the ‘Queue’ class to hold all my ‘work’ inside, and a ‘List’ to hold my threads, for which I’ll be making a simple wrapper for the ‘Thread’ class called ‘ManagedThread’.

First lets define the ‘ManagedThread’ class.  We’ll tack onto the end of the ‘work’ a new delegate to call a ‘Completed’ event.  So this will code will run after the ‘work’ is completed and fire an event that can be monitored later in our code.

   1:  // Author: Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  class ManagedThread
   4:  {
   5:      private    Thread    thread;
   6:      private    Action    work;
   7:      private bool    isRunning = false;
   8:   
   9:   
  10:      public bool IsRunning
  11:      {
  12:          get { return isRunning; }
  13:      }
  14:   
  15:   
  16:      public    event    EventHandler<EventArgs>    Completed;
  17:   
  18:   
  19:      public void AssignWork(Action work)
  20:      {
  21:          this.work = null;    // Clear old work
  22:   
  23:          this.work += work;
  24:      }
  25:   
  26:   
  27:      public void Start()
  28:      {
  29:          if (isRunning) throw new InvalidOperationException("The thread is already started");
  30:   
  31:          work += delegate()    // Add our completed handler to the end of the work
  32:              {
  33:                  if (Completed != null) Completed(this, EventArgs.Empty);    // If there's a completed
  34:                                                                              // handled, call it!
  35:   
  36:                  isRunning = false;
  37:   
  38:                  thread = null;
  39:              };
  40:   
  41:          thread = new Thread(new ThreadStart(work));
  42:   
  43:          isRunning = true;
  44:   
  45:          thread.Start();
  46:      }
  47:   
  48:   
  49:      public void Stop()
  50:      {
  51:          if (!isRunning) return;    // Not running anyway
  52:   
  53:          if (thread.ThreadState != ThreadState.Stopped) thread.Abort();
  54:      }
  55:  }
  56:   

Now lets create a class to hold the threads and handle the work queue.  We’re going to add a ‘Completed’ event to this class also, but this is going to only fire when we’re ‘Completed’ ALL the work.  It can potential fire more than once (it will fire when the queue is empty, and there are no threads running – i.e. all the work assigned has been completed).

  57:   
  58:  class ThreadQueue
  59:  {
  60:      public enum QueueStatus
  61:      {
  62:          Stopped,
  63:          Stopping,
  64:          Started
  65:      }
  66:   
  67:   
  68:      public    event    EventHandler<EventArgs>    Completed;
  69:   
  70:      private            Queue<Action>            workQueue    = new Queue<Action>();
  71:      private            List<ManagedThread>        threads        = new List<ManagedThread>();
  72:   
  73:      public    int         MaxThreads            = 10;
  74:      private    int         runningThreads        =  0;
  75:      private    bool        threadingMoreWork    = false;
  76:      private QueueStatus status                = QueueStatus.Stopped;
  77:   
  78:   
  79:      public QueueStatus Status
  80:      {
  81:          get { return status; }
  82:          set { status = value; }
  83:      }
  84:   
  85:   
  86:      public int RunningThreads
  87:      {
  88:          get { return runningThreads; }
  89:          set { runningThreads = value; }
  90:      }
  91:   
  92:   
  93:      public void AssignWork(Action work)
  94:      {
  95:          lock (workQueue)
  96:          {
  97:              workQueue.Enqueue(work);
  98:          }
  99:      }
 100:   
 101:   
 102:      public int WorkQueueSize()
 103:      {
 104:          return workQueue.Count;
 105:      }
 106:   
 107:   
 108:      public void Start()
 109:      {
 110:          if (status != QueueStatus.Stopped) throw new InvalidOperationException("Cannot start when Status != Stopped");
 111:   
 112:          status = QueueStatus.Started;
 113:   
 114:          ThreadMoreWork();
 115:      }
 116:   
 117:   
 118:      private void ThreadMoreWork()
 119:      {
 120:          threadingMoreWork = true;
 121:   
 122:          while (status == QueueStatus.Started && runningThreads < MaxThreads)
 123:          {    // If there's more to do, thread more work
 124:              lock (workQueue)
 125:              {
 126:                  if (workQueue.Count > 0)
 127:                  {
 128:                      lock (threads)
 129:                      {
 130:                          var thread = (ManagedThread)null;
 131:   
 132:                          if ((thread = AvailableThread()) == null)
 133:                          {    // If there's no ManagedThreads not 'Running', create a new one
 134:                              thread = new ManagedThread();
 135:   
 136:                              thread.Completed += delegate(object sender, EventArgs args)
 137:                                  {    // When the thread is completed, reduce the runningthread counter
 138:                                      runningThreads--;
 139:  
 140:                                      lock (workQueue)
 141:                                      {
 142:                                          if (workQueue.Count == 0 && runningThreads == 0)
 143:                                          {    // All work is done, queue is empty
 144:                                              lock (threads)
 145:                                              {
 146:                                                  threads.Clear();
 147:                                              }
 148:   
 149:                                              status                = QueueStatus.Stopped;
 150:                                              threadingMoreWork    = false;
 151:   
 152:                                              if (Completed != null)Completed(this, EventArgs.Empty);
 153:                                          }
 154:                                      }
 155:   
 156:                                      if (!threadingMoreWork) ThreadMoreWork();    // Thread more work again
 157:                                  };
 158:   
 159:                              threads.Add(thread);
 160:                          }
 161:   
 162:                          thread.AssignWork(workQueue.Dequeue());    // Assign work from the queue to the new thread
 163:   
 164:                          runningThreads++;    // Increase the runningthread counter
 165:   
 166:                          thread.Start();        // Start the thread
 167:                      }
 168:                  }
 169:              }
 170:          }
 171:   
 172:          threadingMoreWork = false;
 173:      }
 174:   
 175:   
 176:      public void Stop()
 177:      {
 178:          status = QueueStatus.Stopping;    // Indicate stopping is in progess
 179:   
 180:          lock (threads)
 181:          {
 182:   
 183:              var active    =
 184:                  (    // Get a list of the active threads
 185:                      from    item
 186:                      in        threads
 187:                      where    item.IsRunning
 188:                      select    item
 189:                  ).ToList();
 190:   
 191:              active.ForEach(delegate(ManagedThread thread)
 192:                  {    // Stop each thread
 193:                      thread.Stop();
 194:                  });
 195:   
 196:              RunningThreads = 0;    // There are no more threads running, so set to 0
 197:   
 198:              threads.Clear();    // Clear out the ManagedThread List
 199:   
 200:              if (Completed != null) Completed(this, EventArgs.Empty);    // If there's a completed
 201:                                                                          // handler call it
 202:          }
 203:      }
 204:   
 205:   
 206:      private ManagedThread AvailableThread()
 207:      {
 208:          var matches =
 209:              (    // Use LINQ to get the threads not running
 210:                  from    item
 211:                  in        threads
 212:                  where    !item.IsRunning
 213:                  select    item
 214:              );
 215:   
 216:          if (matches.Count() == 0) return null;    // if there is none, return a null
 217:   
 218:          return matches.First();    // Otherwise, return the first one in the enumeration
 219:      }
 220:  }
 221:   

As you can see, when new work is assigned, we enter it into our ‘Queue<Action>’ class called ‘workQueue’ .  The function ‘ThreadMoreWork’ is used to start up new threads (if needed).  When we create a new thread and add it into ‘threads’ we hook up the ‘Completed’ event of that thread to call ‘ThreadMoreWork’ (if it’s not already running).  This means as soon as a thread is completed, we’re going to check if we need to start another one – If we do, well, we do!  In our ’stop’ function, we’re using LINQ to find all the running threads, and using the very handy ‘ForEach’ function to Stop all the individual threads.  Then we fire the ‘Completed’ event.

Now we have a simple Console application to demonstrate the classes.  It’s going to queue up 100 pieces of ‘work’ (all will just print a ‘.’ to Console).  We’ll leave the maximum threads at the default we defined earlier (10).  We also have a timer setup to run every 5 seconds and report the progress.  We’ve hooked up the ‘Completed’ event to print ‘Completed’ to console when we’re all done.

 222:   
 223:  class Program
 224:  {
 225:      static void Main(string[] cargs)
 226:      {
 227:          var threadQueue = new ThreadQueue();
 228:          var checkTimer    = new Timer(delegate
 229:              {    // Poll for updated progress every 5 seconds
 230:                  Console.WriteLine("\nThread Information Update! Running={0}, Remaining={1}", threadQueue.RunningThreads, threadQueue.WorkQueueSize());
 231:   
 232:              }, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
 233:   
 234:          threadQueue.Completed += delegate(object sender, EventArgs args)
 235:              {
 236:                  // We've finished, stop the checkTimer and notify Console
 237:                  checkTimer.Dispose();
 238:                  Console.WriteLine("\nCompleted!");
 239:              };
 240:   
 241:          for (int i=0; i<100; i++)
 242:          {    // Queue up our test work
 243:              threadQueue.AssignWork(delegate()
 244:                  {
 245:                      Console.Write(".");
 246:   
 247:                      Thread.Sleep(new Random().Next(5000));
 248:                  });
 249:          }
 250:   
 251:          Console.WriteLine("(Press enter to stop early)");
 252:   
 253:          threadQueue.Start();    // Start processing
 254:   
 255:          Console.ReadLine();
 256:   
 257:          if (threadQueue.Status != ThreadQueue.QueueStatus.Stopped) threadQueue.Stop();
 258:   
 259:          Console.ReadLine();    // Pause so we can see the output
 260:      }
 261:  }

Run it, and the output should look a little like this…

(Press enter to stop early)
......................
Thread Information Update! Running=10, Remaining=78
................
Thread Information Update! Running=10, Remaining=62
....................
Thread Information Update! Running=10, Remaining=42
....................
Thread Information Update! Running=10, Remaining=22
......................
Thread Information Update! Running=10, Remaining=0
Completed!

Job done.

Download Visual Studio 2010 Project (8.03k)

Tags: , , , , ,


Leave a Reply

Mar 11 2010

Locking and multi-threading

Category: ThreadingMike Lovell @ 9:58 pm

I noted over the last few days a lot of questions about ‘lock’ came up on the Microsoft Newsgroups.  I’ve come up with a nice demonstration of the flow of a multi-threaded application with and without locking.

Often in a multi-threaded application, you will have shared resources that all the threads need to use.  Now if those resources do not allow simultaneous access (a good example of this is writing to a text file) you’re going to end up throwing an exception if you try and use the same shared resource from two different threads at once, and you don’t use locking.

Lets move onto the example (the project can be downloaded at the bottom of this article)…

First lets make a class which can simulate a shared object and doesn’t like being called simultaneously.  It’s going to print ‘!’ to console if a ‘collision’ has occurred (where in a real world application, an Exception would occur) when the function ‘Write’ is used - If the function isn’t called simultaneously, it will just print ‘.’

   1:  class KindOfASync
   2:  {
   3:      bool writing = false;
   4:   
   5:      public void Write()
   6:      {
   7:          if (writing)
   8:          {
   9:              Console.Write("!");
  10:              return;
  11:          }
  12:   
  13:          writing = true;
  14:   
  15:          Console.Write(".");
  16:   
  17:          writing = false;
  18:      }
  19:  }
  20:   

Okay, pretty simple class.  Lets up the complication 100x! :-)   We’ll now create a few constants to define how many threads we want to use at once and the amount of iterations (the amount of times we’ll make the ‘Write’ call to our class above).  We’ll then make two ‘Thread’ and ‘Action’ arrays, ‘___A’ will demonstrate not using locks, and ‘___B’ will demonstrate using locks.  The ‘Action’ class is a great way for us to queue up all the work we want our threads to do.

  21:   
  22:  class Program
  23:  {
  24:      const    int    ThreadsToUse    = 10;
  25:      const    int    Iterations        = 300;
  26:   
  27:   
  28:      static void Main(string[] args)
  29:      {
  30:          var myClass        = new KindOfASync();
  31:   
  32:          var threadPoolA    = new Thread[ThreadsToUse];
  33:          var threadPoolB    = new Thread[ThreadsToUse];
  34:  
  35:          var workA        = new Action[ThreadsToUse];
  36:          var workB        = new Action[ThreadsToUse];

Now lets queue up all the work we want our threads to handle.  We’ll evenly divide the iterations between our threads by using the ‘modulus %’.  We’re going to use the int ’completed’ to detect when we’ve completed our iterations

  37:   
  38:          var completed    = 0;
  39:   
  40:          for (int i=0; i < Iterations; i++)
  41:          {
  42:              var threadInUse = i % ThreadsToUse;
  43:   
  44:              workA[threadInUse] += delegate()
  45:                  {
  46:                      myClass.Write();
  47:   
  48:                      completed++;
  49:                  };
  50:   
  51:              workB[threadInUse] += delegate()
  52:                  {
  53:                      lock (myClass)
  54:                          {
  55:                              myClass.Write();
  56:                          }
  57:   
  58:                      completed++;
  59:                  };
  60:          }
  61:   

Now lets tell ‘threadPoolA’ to work through ‘workA’ (no locking) and wait for it to complete.

  62:          Console.WriteLine("Running 'threadPoolA' (WITHOUT locking)");
  63:   
  64:          for (int i=0; i<ThreadsToUse; i++)
  65:          {
  66:              threadPoolA[i] = new Thread(new ThreadStart(workA[i]));
  67:              threadPoolA[i].Start();
  68:          }
  69:   
  70:          while (completed < Iterations)
  71:          {
  72:              Thread.Sleep(10);
  73:          }
  74:   

Now lets tell ‘threadPoolB’ to work through ‘workB’ (locking) and wait for it to complete

  75:          Console.WriteLine("\n");
  76:  
  77:   
  78:          completed = 0;
  79:   
  80:          Console.WriteLine("Running 'threadPoolB' (WITH locking)");
  81:   
  82:          for (int i=0; i<ThreadsToUse; i++)
  83:          {
  84:              threadPoolB[i] = new Thread(new ThreadStart(workB[i]));
  85:              threadPoolB[i].Start();
  86:          }
  87:   
  88:          while (completed < Iterations)
  89:          {
  90:              Thread.Sleep(10);
  91:          }
  92:   
  93:   
  94:          Console.ReadLine();
  95:      }
  96:  }

And the results

Running 'threadPoolA' (WITHOUT locking)
...!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!...............................................
................................................................................
..................................................!.............................
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!..............................
Running 'threadPoolB' (WITH locking)
................................................................................
................................................................................
................................................................................
............................................................

The amount of ‘!’ you get will vary depending on the amount of iterations, the amount of threads, and your processor and the other work your computer is doing when it runs.  ‘lock’ allows you to obtain a mutual-exclusive lock on an object whilst inside the statement block, releasing it when it’s complete.  Not using it correctly can cause many headaches.

Some other blogs covering the subject:

Download Visual Studio 2010 Project (6.48k)

Tags: , , , , , , ,


Leave a Reply

Mar 10 2010

Object Initializers, delegates, anonymous types, type inference and LINQ

Category: UncategorizedMike Lovell @ 9:04 pm

I thought I’d put together a quick and nasty demo showing the use of object initializers, delegates, anonymous types, type inference and LINQ in one place.

The main reason for the existence of ‘var’ is to support anonymous types (although you’ll notice I use ‘var’ practically everywhere, that’s just my style!).

I can define a new type in my code simply by implying its properties. For example:

   1:    var myType = new
   2:        {
   3:            ParamA = "valuea",
   4:            ParamB = "valueb",
   5:            Number  = 123
   6:        }

The compiler (and the VS.NET environment, as we can use intellisense against it) creates the class definition internally. We can now access the properties of that object, just as if we defined it explicitly:

   1:  Console.WriteLine("{0} {1} {2}", myType.ParamA, myType.ParamB, Number);

Why? Well I guess the most common reason for using anonymous types is to return a subset of data from a LINQ query. This is something we’ll do in the demo.

I like to use the type inference capability of ‘var’ to make my code more (in my mind!) cleaner. For example:

   1:  MyClass classObject = new MyClass();

Can be written as:

   1:  var classObject = new MyClass();

I think the later looks better, it seems kinder of my eyes but it’s a personal preference thing, so don’t follow me on that habit just for the sake of it! :-)

I’m also a heavy user of ‘Object initializers’ rather than constructors. Although when you approach more complex classes there often is a need to control the instantiation of an object more tightly and go with the constructor route. ‘Object initializers’ allow me to write nice readable code because it uses named parameters (note: you can now use named parameters with constructors) and it’s nice to not have to write constructors for simple classes. So my code might look a little like this:

   1:  var classObject = newMyPersonClass()
   2:      {
   3:          FirstName = "Mike",
   4:          LastName = "Lovell"
   5:      };

Delegates and LINQ are pretty vast topics, so I’m not going to attempt to cover them apart from to demonstrate their use in a way that might be helpful, so on to the demo…

First, lets declare a couple of classes to use.  For this we’re going to use a simple class called ‘Person’, and a collection of ‘Person’ (by inheriting List<Person>) called ‘People’

   1:  // Author: Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  class Person
   4:  {
   5:      public    stringFirstName = "";
   6:      public    stringLastName = "";
   7:  }
   8:   
   9:   
  10:  class People : List<Person>
  11:  {
  12:  }
  13:  

Now lets define a new instance of our collection and fill it with some test data.  As we haven’t defined any constructors, we’re going to use ‘Object initializers’ to define the values of ‘FirstName’ and ‘LastName’

  14:   
  15:  class Program
  16:  {
  17:      static void Main(string[] args)
  18:      {
  19:          var people = new People();
  20:   
  21:          people.Add(new Person()
  22:              {
  23:                  FirstName    = "Bob",
  24:                  LastName    = "Smith"
  25:              });
  26:   
  27:          people.Add(new Person()
  28:              {
  29:                  FirstName    = "John",
  30:                  LastName    = "Doe"
  31:              });
  32:   
  33:          people.Add(new Person()
  34:              {
  35:                  FirstName    = "Bill",
  36:                  LastName    = "Johnson"
  37:              });
  38:   

Now the delegate, we can use an anonymous delegate to make a rather nifty ‘ForEach’ loop to display the value of each item

  39:          Console.WriteLine("All People:\n");
  40:   
  41:          people.ForEach(delegate(Person person)
  42:              {
  43:                  Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
  44:              });
  45:   

Now the LINQ and anonymous type.  We want to find all the instances of ‘Person’ where their first name begins with a ‘b’, then we’re going to create a anonymous type to store their full name in (of course we could just return it to a string array, but this is a contrived example).  We’ll then display the results to ‘Console’IEnumerable<T> does not have a ‘ForEach’ method so I will be using a more conventional ‘for’ loop!

  46:          var bNames    = from i
  47:                          in people
  48:                          where i.FirstName.ToLower().StartsWith("b")
  49:                          select new
  50:                              {
  51:                                  FullName = String.Format("{0} {1}", i.FirstName, i.LastName)
  52:                              };
  53:   
  54:          Console.WriteLine("\nFirst names that start with a 'b':\n");
  55:   
  56:          foreach (var person in bNames)
  57:          {
  58:              Console.WriteLine(person.FullName);
  59:          }
  60:   
  61:          Console.ReadLine();
  62:      }
  63:  }

And there we have it.

Download Visual Studio 2010 Project (6.69k)

Tags: , , , , , , ,


Leave a Reply

Mar 09 2010

Don’t shoot the messenger, don’t hang the UI!

Category: WPFMike Lovell @ 2:29 pm

I think everyone is guilty of this to an extent.  How often do  you execute code that ‘could’ take a long time to execute, under the UI thread?  The end-user presses a button, your code does it stuff, in the meantime the UI is, well, hung!  Sometimes it’s almost unnoticeable, a quick 500ms pause – But that code still shouldn’t be in there.  Because hangs can be minor, they will sometimes go unnoticed.

I thought I’d write a quick example of the right and wrong ways of dealing with code triggered from the UI thread.  At the bottom of the post is a Visual Studio 2010 Project which demonstrates this.  You will have to excuse my obsession with delegates!

First of all, I’m going to define a private ‘Thread’ which is going to handle my background work (Line 5):

   1:  // Author: Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  public partial class MainWindow : Window
   4:  {
   5:      private Thread    workerThread;
   6:   
   7:   
   8:      public MainWindow()
   9:      {
  10:          InitializeComponent();
  11:      }
  12:   

In this WPF project, I have two buttons to demonstrate each method of doing things, called ‘buttonStartRight’ and ‘buttonStartWrong’.  Lets just make a little function to allow us to enable/disable them both at the same time

  13:   
  14:      private void SetButtonsIsEnabled(bool value)
  15:      {
  16:          buttonStartRight.IsEnabled    = value;
  17:          buttonStartWrong.IsEnabled    = value;
  18:      }
  19:   

Okay, now the wrong way to do it!

  20:   
  21:      private void buttonStartWrong_Click(object sender, RoutedEventArgs e)
  22:      {
  23:          SetButtonsIsEnabled(false);
  24:   
  25:          for (int i=0; i<100; i+= 10)
  26:          {
  27:              Thread.Sleep(1000);
  28:  
  29:              progress.Value = (double)i;
  30:          }
  31:   
  32:          SetButtonsIsEnabled(true);
  33:      }
  34:   

Although it may appear that this code will run nicely, it won’t (try it).  What will happen?  Nothing, until the entire function ’buttonStartWrong_Click’ has completed.  The progress bar WON’T be updated at each step, the buttons WON’T have ‘isEnabled’ set to false (from our function call on Line 21).

You’ll click the button, the UI thread will be blocked (the button won’t even pop up again indicating it’s clicked).  It’s a good old fashion hang (Ah, those VB6 days!).

So what is the right way?  Lets use that ‘Thread’ we declared earlier for this function:

  35:   
  36:      private void buttonStartRight_Click(object sender, RoutedEventArgs e)
  37:      {
  38:          SetButtonsIsEnabled(false);
  39:   
  40:          workerThread = new Thread(new ThreadStart(delegate()
  41:              {
  42:                  for (int i=0; i<100; i+= 10)
  43:                  {
  44:                      Thread.Sleep(1000);
  45:  
  46:                      Dispatcher.BeginInvoke((MethodInvoker)delegate()
  47:                          {
  48:                              progress.Value = (double)i;
  49:                          }, null);
  50:                  }
  51:   
  52:                  Dispatcher.BeginInvoke((MethodInvoker)delegate()
  53:                      {
  54:                          SetButtonsIsEnabled(true);
  55:                      }, null);
  56:              }));
  57:   
  58:          workerThread.Start();
  59:      }
  60:  }

So I’ve created an instance of a‘Thread’ with an anonymous delegate containing the code I want to run (Line 40).  As I’m now in a different thread from the UI, I won’t be allowed to directly work with its controls.  I need to use the ‘Dispatcher’ to talk to the UI thread.  I’ve made anonymous delegates for each of my calls back to the UI thread to make updates (to both the progress bar on Line 46, and the buttons on line 52). 

Et Voila

Some other bloggers covering multi-threading in WPF:

Download Visual Studio 2010 Project (13.5k)

Tags: , , , , , ,


One Response to “Don’t shoot the messenger, don’t hang the UI!”

  1. Pacome says:

    Light and clear. I like this article.

Leave a Reply

Mar 09 2010

Minimal WCF server/client WITHOUT app.config

Category: WCFMike Lovell @ 11:51 am

“Could not find default endpoint element that references contract”“This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element”

Punch nearest person in face!

I like to stick the majority of my code into class libraries, and make it so they have no external dependencies. If the end-application has to implement a “app.config” file, I don’t like this limitation. Here’s a minimal example of a WCF server/client application that removes that requirement (if you want to use callbacks, you need to use the DuplexChannelFactory).

   1:  // Author: Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  using System;
   4:  using System.Collections.Generic;
   5:  using System.Linq;
   6:  using System.Text;
   7:   
   8:  using System.ServiceModel;  // Additional
   9:   
  10:   
  11:  namespace wcfwithoutappconfig
  12:  {
  13:      class Program
  14:      {
  15:          static void Main(string[] args)
  16:          {
  17:              var server    = new ServerWrapper();
  18:              var client    = new Client();
  19:   
  20:              Console.WriteLine("2 + 2 = {0}", client.CallAdd(2, 2));
  21:              Console.WriteLine("2 - 2 = {0}", client.CallSubtract(2, 2));
  22:   
  23:              server.Close();
  24:          }
  25:      }
  26:   
  27:   
  28:      [ServiceContract(Namespace="dotdynamite.local")]
  29:      interface IServer
  30:      {
  31:          [OperationContract]
  32:          int Add(int x, int y);
  33:   
  34:          [OperationContract]
  35:          int Subtract(int x, int y);
  36:      }
  37:   
  38:   
  39:      public class ServerWrapper
  40:      {
  41:          private    ServiceHost    serviceHost;
  42:   
  43:          public ServerWrapper()
  44:          {
  45:              serviceHost = new ServiceHost(typeof(Server));
  46:   
  47:              serviceHost.AddServiceEndpoint
  48:                  (
  49:                      typeof(IServer),
  50:                      new NetTcpBinding(),
  51:                      "net.tcp://127.0.0.1:5555/DotDynamite"
  52:                  );
  53:   
  54:              serviceHost.Open();
  55:          }
  56:   
  57:   
  58:          public void Close()
  59:          {
  60:              if (serviceHost != null)
  61:              {
  62:                  serviceHost.Close();
  63:                  serviceHost = null;
  64:              }
  65:          }
  66:      }
  67:   
  68:   
  69:      public class Server : IServer
  70:      {
  71:          public int Add(int x, int y)
  72:          {
  73:              return x + y;
  74:          }
  75:   
  76:   
  77:          public int Subtract(int x, int y)
  78:          {
  79:              return x - y;
  80:          }
  81:      }
  82:   
  83:   
  84:      public class Client
  85:      {
  86:          private    ChannelFactory<IServer>    channel;
  87:          private    IServer                    server;
  88:   
  89:   
  90:          public Client()
  91:          {
  92:              channel = new ChannelFactory<IServer>
  93:                  (
  94:                      new NetTcpBinding(),
  95:                      new EndpointAddress("net.tcp://127.0.0.1:5555/DotDynamite")
  96:                  );
  97:   
  98:              server = channel.CreateChannel();
  99:          }
 100:   
 101:   
 102:          public int CallAdd(int x, int y)
 103:          {
 104:              return server.Add(x, y);
 105:          }
 106:   
 107:   
 108:          public int CallSubtract(int x, int y)
 109:          {
 110:              return server.Subtract(x, y);
 111:          }
 112:      }
 113:  }

Download Visual Studio 2010 Project (6.74k)

 There are also some other ways around the problem:

Tags: , , , ,


2 Responses to “Minimal WCF server/client WITHOUT app.config”

  1. Pacome says:

    Exactly what I was looking for, and the links you give are useful too.
    I discovered your blog today, and I hope you will continue this way.
    Thanks for sharing your experience.

  2. AndrewM says:

    Just tried what you suggest but I get an exception on trying to instantiate the proxy (your myClient class):

    (the only difference is I extend ClientBase as I need to set the ClientCertificate – it seems the only way round this is to still have a config file!)

    Error:
    System.InvalidOperationException was unhandled
    Message=Could not find default endpoint element that references contract ‘VPSTransferLibrary.VPSWcfTransport.IReceiveService’ in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.

Leave a Reply

Mar 09 2010

Catching multiple Exceptions in a single block

Category: Exception HandlingMike Lovell @ 11:19 am

Don’t you hate writing multiple catch blocks which duplicate code? There’s a quick way around this by using the “is” statement.

   1:  // Author: Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  try
   4:  {
   5:      // Code
   6:  }
   7:  catch (Exception e)
   8:  {
   9:      if (
  10:              e is OverflowException
  11:              || e is ArgumentNullException
  12:              || e is IndexOutOfRangeException
  13:          )
  14:      {
  15:          // Some other handling
  16:      }
  17:      else
  18:      {
  19:          throw;
  20:      }
  21:  }

Problem solved!

Tags: , , ,


Leave a Reply