InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

fun with .NET 4 expressions – Light speed edition

A few days ago I posted an article about the new .NET Expression features in .NET 4.0 (Fun with .NET 4 expressions). A few people commented and wrote the this was a pretty expensive way to synchronize data. Of course it was – performance wasn’t a design consideration. I merely followed the two rules of optimization:

  1. Don’t do it.
  2. (For experts only!) Don’t do it now.

And since the synchronization process was fast enough, I didn’t care.

However, just for the fun of it, I did some performance optimization and it is pretty amazing. The thing which made the original code rather slow was the fact that the same expressions were compiled over and over again. So an obvious improvement was to cache the compiled expressions and reuse them. So I introduced two dictionaries to hold the compiled expressions:

private static readonly Dictionary<Type, object> _SetterCache = new Dictionary<Type, object>();
private static readonly Dictionary<Type, object> _GetterCache = new Dictionary<Type, object>();

You may wonder why the type of the dictionary is Dictionary<Type, object>. The reason for this is that there is no other common base class for the type Func<TSource, TProperty>. The following this method checks the cache and compiles the expression if required:

private static Func<TTarget, TProperty> GetGetterMethod<TTarget, TProperty>(Expression<Func<TTarget, TProperty>> targetSelector)
{
    object getterObject;
    Func<TTarget, TProperty> getterMethod;
    var selectorType = targetSelector.Type;

    if (!_GetterCache.TryGetValue(selectorType, out getterObject))
    {
        getterMethod = targetSelector.Compile();
        _GetterCache[selectorType] = getterMethod;
    }
    else
    {
        getterMethod = (Func<TTarget, TProperty>) getterObject;
    }
    return getterMethod;
}

I added a similar method to handle the update expression accordingly.

Finally, I hacked together a small test program which used the Stopwatch class to measure the synchronization speed. The result is quite impressing. Synchronizing an object with two properties 10,000 times yielded these results:

Elapsed for 10000 rounds (Slow): 00:00:08.0471936
Elapsed for 10000 rounds (Fast): 00:00:00.2009293

That is quite an improvement.

I’ve attached the source code to this post, so you can measure yourself.

Downloads


Posted by Henning Krause on Sunday, December 5, 2010 9:00 PM, last modified on Sunday, December 5, 2010 8:38 PM
Permalink | Post RSSRSS comment feed

Using Code Contracts Visual Studio and with Resharper

CodeContracts are a new feature to write assumptions in .NET programs. A version for .NET 3.5 is available from the Microsoft Code Contracts. With .NET 4 they are part of the BCL. Unfortunately, they do nothing out of the box – a binary rewriter is required to enable runtime checking. The rewriter is also available from the Microsoft site specified above.

Enabling Code Contracts

Once the Code Contracts are installed on a machine, they must be enabled in each Visual Studio project by specifying the CONTRACTS_FULL conditional compilation symbol in the properties of a project:

ConditionalSymbol

Next, enable the runtime checking on the Code Analysis tab:

EnableRuntimeChecking

Now you can use the Code Contracts within the project. Here is a small sample application:

using System;
using System.Diagnostics.Contracts;

namespace SampleApplication
{
    internal class Program
    {
        public static int Divide(int a, int b)
        {
            Contract.Requires(b != 0);
            Contract.Ensures(a != 0 ? Contract.Result<int>() != 0 : Contract.Result<int>() == 0);

            return a/b;
        }

        private static void Main()
        {
            Console.Out.WriteLine("Divide(4, 2) = {0}", Divide(2, 2));
            Console.Out.WriteLine("Divide(4, 0) = {0}", Divide(4, 0));
        }
    }
}

It’s just a small division method which has one pre- and one post-condition: The method requires b not to be 0. The post-condition specifies that the result of the method is 0 if a is 0 and not 0 when a is not 0. Very simple. If you run the program, it will throw an exception on the second execution of the Divide method, because b is 0 in this case:

Precondition faileed

Integration with Resharper

If you are using Resharper, you are accustomed to the null-reference checking the tool performs as you type. This is quite handy to spot null-references during design-time vs. run-time.

Here is another method which is annotated with code contracts:

 

NullReference

Notice the squiggles under the name variable and the hint to a System.NullReferenceException. If you would replace the first line of the method with a

if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");

the warning would be gone, because Resharper would sense that the code path with the if-statement is never executed if name is null.

To enabled this feature with Code Contracts, a file with certain annotations must be placed in the directory C:\Program Files\JetBrains\ReSharper\v5.1\Bin\ExternalAnnotations\mscorlib (C:\Program Files (x86)\JetBrains\ReSharper\v5.1\Bin\ExternalAnnotations\mscorlib on x64 systems). The file is attached at the end of this post.

Visual Studio Editor Code Contracts extension

A Visual Studio extension is available from the Code Contracts team. It can be downloaded via the Extension Manager. It visualizes code contracts directly in the editor.

image

Credits

The Microsoft.CodeContracts.xml is taken from a Youtrack issue http://youtrack.jetbrains.net/issue/RSRP-190566. I’ve modified the file to work with .NET 4.0.

Downloads


Posted by Henning Krause on Thursday, November 18, 2010 5:07 PM, last modified on Thursday, November 25, 2010 5:08 PM
Permalink | Post RSSRSS comment feed

Workflow Foundation Part III: Participating in persistence

This is the third post about the Workflow Foundation 4. The first two posts can be found here and here.

In the second article I introduced the IncrementExtension which asynchronously increments an integer value and waits one second each time it is called. The activity used bookmarks to stop and resume the workflow while it is running. The problem is this: When the application is forcefully stopped and restarted, the index will start again at zero. This is a shame, since the workflow instance is already persisted to the database between each call.

Enter PersistenceParticipant. This is a base class for extension that which to persist data to the instance store configured for a workflow application. The PersistenceParticipant class has three virtual methods that enable the persistence functionality. Here is the IncrementExtension from the last post extended with the persistence features:

   1: using System;
   2: using System.Activities;
   3: using System.Activities.Hosting;
   4: using System.Activities.Persistence;
   5: using System.Collections.Generic;
   6: using System.Threading;
   7: using System.Xml.Linq;
   8:  
   9: namespace WorkflowConsoleApplication1
  10: {
  11:     class IncrementExtension : PersistenceParticipant, IWorkflowInstanceExtension
  12:     {
  13:         private static XName PersistencePropertyName = XNamespace.Get("urn:example.com:WorkflowDemo/1.0/Increment").GetName("LastValue");
  14:  
  15:         int _Index;
  16:         private WorkflowInstance _Instance;
  17:         Bookmark _Bookmark;
  18:  
  19:         public void Increment(Bookmark bookmark)
  20:         {
  21:             ThreadPool.QueueUserWorkItem(state =>
  22:             {
  23:                 Thread.Sleep(1000);
  24:                 var value = Interlocked.Increment(ref _Index);
  25:                 _Bookmark = bookmark;
  26:                 ContinueWorkflow(value);
  27:             }, null);
  28:         }
  29:  
  30:         private void ContinueWorkflow(int value)
  31:         {
  32:             _Instance.BeginResumeBookmark(_Bookmark, value, CompleteResume, null);
  33:         }
  34:  
  35:         public void CompleteResume(IAsyncResult ar)
  36:         {
  37:             var result = _Instance.EndResumeBookmark(ar);
  38:         }
  39:  
  40:         IEnumerable<object> IWorkflowInstanceExtension.GetAdditionalExtensions()
  41:         {
  42:             yield break;
  43:         }
  44:  
  45:         void IWorkflowInstanceExtension.SetInstance(WorkflowInstance instance)
  46:         {
  47:             _Instance = instance;
  48:         }
  49:  
  50:         protected override void CollectValues(out IDictionary<XName, object> readWriteValues, out IDictionary<XName, object> writeOnlyValues)
  51:         {
  52:             readWriteValues = new Dictionary<XName, object> 
  53:                 {
  54:                     {PersistencePropertyName, new KeyValuePair<Bookmark, int>(_Bookmark, _Index)}
  55:                 };
  56:             writeOnlyValues = null;
  57:         }
  58:  
  59:         protected override void PublishValues(IDictionary<XName, object> readWriteValues)
  60:         {
  61:             var keyvalue = (KeyValuePair<Bookmark, int>)readWriteValues[PersistencePropertyName];
  62:             _Index = (int)keyvalue.Value;
  63:             _Bookmark = (Bookmark)keyvalue.Key;
  64:  
  65:             ContinueWorkflow(_Index);
  66:         }
  67:     }
  68: }

To save data to the instance store, a unique id for the the data, represented by an XName instance. This can be created using the XNamespace class (see line 13). With this unique id, the data of the extension instance can be persisted to the instance store. To save the data the extension needs to override the CollectValues method and add the properties to be persisted to the readWriteValues (lines 50 to 56). The runtime uses the DataContractSerializer to serialize the data. Since .NET 3.5 practically every class that has the SerializableAttribute on its class and/or implements the ISerializable interface can be serialized. At minimum, this method should serialize the bookmark. This is required to continue the workflow when it’s restarted.

When the workflow is restarted the runtime calls the PublishValues method on the extension to load the instance data from the store (line 59-66). This method also should check whether to resume any bookmarks to continue the workflow.

That’s all.


Posted by Henning Krause on Wednesday, October 21, 2009 9:39 PM, last modified on Monday, November 29, 2010 7:49 PM
Permalink | Post RSSRSS comment feed

Workflow Foundation 4 – Part II: NativeActivities and Extensions

This is the second post about Workflow Foundation 4, Beta 2. This time, it’s about native activities and custom extensions. The sample used here is the same as in my last post (Persistence in Workflow Foundation 4). In that post, I used a simple workflow which incremented a integer value by one each time it was executed. To make things more interesting, the custom activity does this in an asynchronous manner.

The activity is a rather simple one, since it uses an extension to do the actual work:

   1: using System.Activities;
   2:  
   3: namespace WorkflowConsoleApplication1
   4: {
   5:     public class IncrementActivity : NativeActivity
   6:     {
   7:         public OutArgument<int> Result { get; set; }
   8:  
   9:         protected override bool CanInduceIdle { get { return true; } }
  10:  
  11:         protected override void Execute(NativeActivityContext context)
  12:         {
  13:             var extension = context.GetExtension<IncrementExtension>();
  14:  
  15:             var bookmark = context.CreateBookmark("test", IncrementCallback);
  16:             extension.Increment(bookmark);
  17:         }
  18:  
  19:         private void IncrementCallback(NativeActivityContext context, Bookmark bookmark, object value)
  20:         {
  21:             Result.Set(context, (int)value);
  22:         }
  23:     }
  24: }

The action has an out argument, the Result property. The value written to this argument is incremented by one each time the activity is called. The key to enable automatic workflow persistence are bookmarks. A short summary about bookmarks can be found in plenty of blogs (for example here). But most of them are wrong with their examples: The syntax has changed quite a bit when it comes to how to create bookmarks. When an activity calls the CreateBookmark method, the runtime automatically stops the workflow instance at that point and persists it to the instance store, if configured. The bookmark takes a name and a callback. The workflow instance is resumed, when the callback is called. In this example, the callback function sets the ‘Result’ argument to the value it receives from the extension.

Note that the activity needs to return true in the CanInduceIdle property. Otherwise, a call to CreateBookmark method will throw an exception.

Once the bookmark has been created, it is handed over to the IncrementExtension.

The IncrementExtension has one method that actually does something: The Increment method. It takes a Bookmark instance as input and resumes it after waiting for 1 second on a different thread:

   1: using System;
   2: using System.Activities;
   3: using System.Activities.Hosting;
   4: using System.Collections.Generic;
   5: using System.Threading;
   6:  
   7: namespace WorkflowConsoleApplication1
   8: {
   9:     class IncrementExtension : IWorkflowInstanceExtension
  10:     {
  11:         int _Index;
  12:         private WorkflowInstance _Instance;
  13:         Bookmark _Bookmark;
  14:  
  15:         public void Increment(Bookmark bookmark)
  16:         {
  17:             ThreadPool.QueueUserWorkItem(state =>
  18:             {
  19:                 Thread.Sleep(1000);
  20:                 var value = Interlocked.Increment(ref _Index);
  21:                 _Bookmark = bookmark;
  22:                 ContinueWorkflow(value);
  23:             }, null);
  24:         }
  25:  
  26:         private void ContinueWorkflow(int value)
  27:         {
  28:             _Instance.BeginResumeBookmark(_Bookmark, value, CompleteResume, null);
  29:         }
  30:  
  31:         public void CompleteResume(IAsyncResult ar)
  32:         {
  33:             var result = _Instance.EndResumeBookmark(ar);
  34:         }
  35:  
  36:         IEnumerable<object> IWorkflowInstanceExtension.GetAdditionalExtensions()
  37:         {
  38:             yield break;
  39:         }
  40:  
  41:         void IWorkflowInstanceExtension.SetInstance(WorkflowInstance instance)
  42:         {
  43:             _Instance = instance;
  44:         }
  45:     }
  46: }

To resume the workflow instance, the extension needs to know which instance it should resume. By default, it does not have this info. It only has an instance of a Bookmark. To get the workflow instance associated with an instance of an extension instance, the extension needs to implement the IWorkflowInstanceExtension. This method is called during the initialization of the extension instance.

Given the instance and the bookmark, the extension can now call the BeginResumeBookmark method on the workflow instance.

One question remains: Where does the extension instance come from? Simple, it is provided during the initialization of the workflow:

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         var app = new WorkflowApplication(new Workflow1());
   6:  
   7:         // Specify that the workflow should be persisted everytime it is idle.
   8:         app.PersistableIdle = e => PersistableIdleAction.Persist;
   9:  
  10:         // Add an instance store that is used to persist the workflow.
  11:         app.InstanceStore = new SqlWorkflowInstanceStore("Data Source=(local);Initial Catalog=WorkflowDemo;Integrated Security=True");
  12:  
  13:         app.Extensions.Add(() => new IncrementExtension());
  14:         app.Load(new Guid("1E1A5265-A135-4D42-9D64-2ECCCF22E888"));
  15:         app.Run();
  16:  
  17:         Console.WriteLine("Current Instance id: {0}", app.Id);
  18:  
  19:         Console.ReadLine();
  20:  
  21:         app.Unload();
  22:     }
  23: }

The extension is added to the workflow application in line 13. The app.Extensions.Add method either takes a singleton instance of the extension (which is then used each time the extension is requested) or a factory method which creates a new instance each time the extension is requested.


Posted by Henning Krause on Tuesday, October 20, 2009 1:24 PM, last modified on Monday, November 29, 2010 6:11 PM
Permalink | Post RSSRSS comment feed

Persistence in Workflow Foundation 4 Beta 2

The Workflow Foundation has changed dramatically since .NET 3.5… and many changes have been made even since Beta one. One of the big changes is related to persistence. In earlier versions, either an SqlWorkflowPersistenceService or the and SQLPersistenceProviderFactory was used. Things have become much easier, though, with the release of the second beta of Visual Studio 2010. A workflow can now easily be persisted with a few lines of code. For this sample, I have created a simple workflow which just counts from zero upwards. Since persistence is primarily useful for long-running workflows, I have come up with this example:

image

Obviously, this workflow runs very long… espacially, since the custom IncrementActivity waits one second before incrementing the variable ‘Index’.

To execute the workflow, only a few lines of code are required:

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         var app = new WorkflowApplication(new Workflow1());
   6:  
   7:         // Specify that the workflow should be persisted everytime it is idle.
   8:         app.PersistableIdle = e => PersistableIdleAction.Persist;
   9:         
  10:         // Add an instance store that is used to persist the workflow.
  11:         app.InstanceStore = new SqlWorkflowInstanceStore("Data Source=(local);Initial Catalog=WorkflowDemo;Integrated Security=True");
  12:         
  13:         app.Run();
  14:  
  15:         Console.WriteLine("Current Instance id: {0}", app.Id);
  16:         Console.ReadLine();
  17:  
  18:         app.Unload();
  19:     }
  20: }

Sure, there are simpler ways to execute a workflow but AFAIK only this method support persistence using the SqlWorkflowInstanceStore.

To reload the workflow from the database one line needs to be added to the code (in line 12, just before the app.Run() call):

   1: app.Load(new Guid("1E1A5265-A135-4D42-9D64-2ECCCF22E888"));

Of course, the id needs to be replaced with the instance id of the workflow. Once the workflow is running, the instance id can be retrieved from the app.Id property (as shown in line 15).

That’s all.

To persist workflows to a database, the necessary tables and stored procedures must be created in a database. This can easily be accomplished with two files from the .NET 4 runtime directory under %windir%\Microsoft.NET\Framework\v4.0.21006\SQL\en. The SQL statements from the two files SqlWorkflowInstanceStoreSchema.sql and SqlWorkflowInstanceStoreLogic.sql have to be executed against the target database.


Posted by Henning Krause on Monday, October 19, 2009 8:55 PM, last modified on Tuesday, October 20, 2009 1:24 PM
Permalink | Post RSSRSS comment feed

InfiniTec.DirectoryServices now on CodePlex

I’ve just created my second CodePlex project (the first one being my PushNotification Lister on http://exchangenotification.codeplex.com/). It’s the DirectoryServices.Protocols wrapper I created a while ago. The last version was still based on my old InfiniTec.Threading library which is seriously broken. The new one runs rather flawlessly and is very stable.

I will add example programs soon, I hope.


Posted by Henning Krause on Tuesday, August 11, 2009 9:14 PM, last modified on Monday, November 29, 2010 8:40 PM
Permalink | Post RSSRSS comment feed

Developing Windows Services with .NET

Developing Windows services with .NET is not always easy – sure, one can attach a debugger once the service is started (at least when developing on Windows XP / 2003). But this is not exactly an ‘F5’ experience one has with normal programs or even Websites. Another drawback of the “Attach to process” method is that the start of the service cannot be debugged. A common way to circumvent this is to write a System.Diagnostics.Debugger.Break statement within the first lines. This will bring up the Just-In-Time Debugger window that let’s you choose a debugger. Sadly, this does not work any more with Windows Vista / 2008 because services run on an isolated window station.

Luckily, there is a solution: A windows service is nothing more than a console application that is started slightly differently. One can take advantage of this by starting the service as a stand-alone program when started normally (via F5 or starting the service from the command line). But if the program detects if it is started by the Service Control manager, run it as a service. So, how can a program check whether it is started by the Service control manager? It depends on the user account the program runs under. If it’s running as “LocalSystem”, one can safely assume it’s running as a service. In any other case, the user account token has a special group membership: The System.Security.Principal.WellknownSidType.Service.

The default body of a program.cs file of blank service solution looks like this:

   1: using System.ServiceProcess;
   2:  
   3: namespace WindowsService1
   4: {
   5:     static class Program
   6:     {
   7:         /// <summary>
   8:         /// The main entry point for the application.
   9:         /// </summary>
  10:         static void Main()
  11:         {
  12:             var servicesToRun = new ServiceBase[] 
  13:                                               { 
  14:                                                   new Service1() 
  15:                                               };
  16:             ServiceBase.Run(servicesToRun);
  17:         }
  18:     }
  19: }

With a few additional lines, a comfortable F5 experience can be gained:

   1: using System;
   2: using System.Linq;
   3: using System.Security.Principal;
   4: using System.ServiceProcess;
   5:  
   6: namespace WindowsService1
   7: {
   8:     static class Program
   9:     {
  10:         /// <summary>
  11:         /// The main entry point for the application.
  12:         /// </summary>
  13:         static void Main()
  14:         {
  15:             var identity = WindowsIdentity.GetCurrent();
  16:             var principal = new WindowsPrincipal(identity);
  17:             // Check whether the current user account is the LocalSystem account
  18:             var isLocalSystemUser = 
  19:                 identity.User == new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
  20:  
  21:             if (isLocalSystemUser || principal.IsInRole(new SecurityIdentifier(WellKnownSidType.ServiceSid, null)))
  22:             {
  23:                 var servicesToRun = new ServiceBase[]
  24:                                         {
  25:                                             new Service1()
  26:                                         };
  27:                 ServiceBase.Run(servicesToRun);
  28:             }
  29:             else
  30:             {
  31:                 var service = new Service1();
  32:                 service.StartAsApplication();
  33:             }
  34:         }
  35:  
  36:     }
  37: }

I have added a StartAsApplication() method to the Service1 class, because the OnStart() method of the default service template is protected and therefore not accessible. And that is all there is. The service can now be started by just pressing F5.

Drawbacks

The gain of the F5 experience does not come without a cost – normally, a Windows service runs under a special account (which is hopefully not LocalSystem): NetworkService, LocalService or a dedicated service account. With this approach, the service runs with the permissions of the currently logged on user. Normally, that user account has far more security permissions than the service account would have. For example, the current user might have the permission to host WCF services on arbitrary ports – something only administrators are allowed to do. A service account would need explicit permission to host that service. Another example are private keys of certificates in the LocalComputer store – not accessible for the NetworkService account by default. But if a service needs to access those keys, it won’t fail unless during development. This should be kept in mind.!


Posted by Henning Krause on Saturday, June 13, 2009 12:26 PM, last modified on Monday, November 29, 2010 7:30 PM
Permalink | Post RSSRSS comment feed

pushd kann UNC-Pfade verbinden

Betroffene Produkte

  • Windows 2000
  • Windows XP
  • Windows 2003

Zusammenfassung

Dieser Artikel beschreibt die Benutzung des pushd Befehls um effizienter auf UNC Pfade zu wechseln.

Beschreibung

Der cd Befehl kann nicht in Verzeichniss wechseln, die auf Netzwerklaufwerken liegen. Eine Lösung besteht darin, zunächst mit
net use z: \\server\share
z:
cd path
den Netzwerkpfad auf ein lokales Laufwerk zu mappen, und dann auf eben dieses Laufwerk wechseln.
Jedoch muss man hier drei Befehle eintippen, was bei häufiger Nutzung recht aufwändig ist.

Lösung

Der Befehl pushd kann verwendet werden, um die obigen Befehle zusammen zu fassen:
pushd \\server\share\path
Es wird ein Laufwerksmapping durchgeführt, und das aktuelle Verzeichnis wird gewechselt. Ein weiterer Vorteil dieses Befehls liegt darin, das ein
popd
wieder in das Verzeichnis wechselt, das aktiv war, als der pushd Befehl aufgerufen wurde.

Weitere Informationen

Die obigen drei Befehle können in zwei Befehle zusammen gefasst werden. Dies wird hier sehr gut beschrieben.

Tags: , , , ,

Technorati: , , , ,

Posted by Henning Krause on Friday, December 31, 2004 2:29 PM, last modified on Friday, December 31, 2004 2:36 PM
Permalink | Post RSSRSS comment feed