# Thursday, 28 September 2006

I'm working on a new project these days, and we're going all out with the bleeding edge goodies, including .NET 3.0.  To set the stage, we've got a server that internally calls a WF workflow instance, which is inherently asynchronous, so the interface we expose to clients is a WCF "Duplex Contract" which basically means two sets of one-way messages that are loosely coupled.  Think MSMQ, or other one-way message passing applications. 

[ServiceContract(CallbackContract=typeof(ITestServiceCallback))]

    public interface ITestService

    {

        [OperationContract(IsOneWay=true)]

        void SignOn(SignOnRequest request);

    }

 

    [ServiceContract()]

    public interface ITestServiceCallback

    {

        [OperationContract(IsOneWay = true)]

        void SignOnResponse(SignOnResponse response);

    }

However, we need to call this duplex contract from an ASP.NET application, since that's how we write out clients 80% of the time.  Since HTTP is inherently synchronous, this poses a bit of a challenge.  How do you call a duplex contract, but make it look synchronous to the caller?

The solution I came up with was to use a generated wrapper class that assigns each outgoing message a correlation id (a GUID), than uses that id as a key into a dictionary where it stores a System.Threading.WaitHandle, in this case really an AutoResetEvent.  Then the client waits on the WaitHandle.

When the response comes back (most likely on a different thread) the wrapper matches up the correlation id, gets the wait handle, and signals it, passing the response from the server in another dictionary which uses the WaitHandle as a key.  The resulting wrapper code looks like this:

 

public class Wrapper : ITestServiceCallback

{

    #region private implementation

    private static Dictionary<Guid, WaitHandle> correlationIdToWaitHandle = new Dictionary<Guid,WaitHandle>();

    private static Dictionary<WaitHandle, Response> waitHandleToResponse = new Dictionary<WaitHandle, Response>();

    object correlationLock = new object();

 

    private static void Cleanup(Guid correlationId, WaitHandle h)

    {

        if(correlationIdToWaitHandle.ContainsKey(correlationId))

            correlationIdToWaitHandle.Remove(correlationId);

        if(waitHandleToResponse.ContainsKey(h))

            waitHandleToResponse.Remove(h);

    }

 

    ITestService client = null;

 

    #endregion

 

    public Wrapper()

    {

        client = new TestServiceClient(new InstanceContext(this));

    }

 

    public SignOnResponse SignOn(SignOnRequest request)

    {

        request.CorrelationId = Guid.NewGuid();

        WaitHandle h = new AutoResetEvent(false);

 

        try

        {

            lock (correlationLock)

            {

                correlationIdToWaitHandle.Add(request.CorrelationId, h);

            }

 

            client.SignOn(request);

 

            h.WaitOne();

 

            SignOnResponse response = (SignOnResponse)waitHandleToResponse[h];

 

            return response;

        }

        finally

        {

            Cleanup(request.CorrelationId, h);

        }

    }

 

    #region ITestServiceCallback Members

 

    void ITestServiceCallback.SignOnResponse(SignOnResponse response)

    {

        Guid correlationId = response.CorrelationId;

 

        WaitHandle h = correlationIdToWaitHandle[correlationId];

 

        waitHandleToResponse.Add(h, response);

 

        ((AutoResetEvent)h).Set();

 

        return;

    }

 

    #endregion

}

This worked just fine in my command line test app, but when I moved to an actual Web app, hosted either in IIS or in VisualStudio 2005, I started getting random but very frequent exceptions popping up in my client app, AFTER the synchronous method had completed.  The exception had a very long and pretty incomprehensible call stack

System.ServiceModel.Diagnostics.FatalException was unhandled
Message="Object reference not set to an instance of an object."
Source="System.ServiceModel"
StackTrace:
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Dispatch(MessageRpc& rpc, Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
at System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.ServiceModel.Channels.InputQueue`1.Dispatch()
at System.ServiceModel.Channels.InputQueueChannel`1.Dispatch()
at System.ServiceModel.Channels.ReliableDuplexSessionChannel.ProcessDuplexMessage(WsrmMessageInfo info)
at System.ServiceModel.Channels.ClientReliableDuplexSessionChannel.ProcessMessage(WsrmMessageInfo info)
at System.ServiceModel.Channels.ReliableDuplexSessionChannel.HandleReceiveComplete(IAsyncResult result)
at System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnReceiveCompletedStatic(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
at System.ServiceModel.Channels.ReliableChannelBinder`1.InputAsyncResult`1.OnInputComplete(IAsyncResult result)
at System.ServiceModel.Channels.ReliableChannelBinder`1.InputAsyncResult`1.OnInputCompleteStatic(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
at System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item, ItemDequeuedCallback dequeuedCallback)
at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecurityDuplexSessionChannel.CompleteReceive(IAsyncResult result)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecurityDuplexSessionChannel.OnReceive(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.ReceiveAsyncResult.OnReceive(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
at System.ServiceModel.Channels.ReliableChannelBinder`1.InputAsyncResult`1.OnInputComplete(IAsyncResult result)
at System.ServiceModel.Channels.ReliableChannelBinder`1.InputAsyncResult`1.OnInputCompleteStatic(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
at System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.ServiceModel.Channels.InputQueue`1.Dispatch()
at System.ServiceModel.Channels.InputQueue`1.OnDispatchCallback(Object state)
at System.ServiceModel.Channels.IOThreadScheduler.WorkItem.Invoke()
at System.ServiceModel.Channels.IOThreadScheduler.ProcessCallbacks()
at System.ServiceModel.Channels.IOThreadScheduler.CompletionCallback(Object state)
at System.ServiceModel.Channels.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

Obvious? Not so much.

Interestingly, if I removed the lock around the hashtable insertion in the signon method

            lock (correlationLock)

            {

                correlationIdToWaitHandle.Add(request.CorrelationId, h);

            }

everything worked just fine.  Hmmmm. 

The problem, it turned out, was that ASP.NET uses (by default) a little thing called the SynchronizationContext.  As near as I can tell (I haven't researched this thoroughly, to be honest) one of it's jobs it to make sure that any callbacks get run on the UI thread, thereby obviating the need to call Control.Invoke like you do in WinForms.  In my case, that additional lock was giving something fits, and it was trying to clean stuff up on a thread that wasn't around any more, hence to NullReferenceException. 

The solution was provided by Steve Maine (thanks Steve!).  Unbeknownst to me (since I didn't know there was a SynchronizationContext) you can turn it off.  Just add a CallbackBehavior attribute to your client side code, with UseSynchronizationContext=false.  So now my wrapper class looks like this

[CallbackBehavior(UseSynchronizationContext=false)]

public class Wrapper : ITestServiceCallback

and everything works fine. 

I'm open to other ways of making this work, so I'd love to hear from people, but right now everything is at least functioning the way I expect.  Several people have wondered why we don't just make the server-side interface synchronous, but since we are calling WF internally, we'd essentially have to pull the same trick, only on the server side.  I'd rather burn the thread on the client then tie up one-per-client on the server.  Again, I'm open to suggestions.

CodeGen | Indigo | Work
Thursday, 28 September 2006 10:02:46 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [3]  | 
# Tuesday, 27 June 2006

I took Steve’s comment to heart, and got rid of the two places I had been “forced” to use the CodeSnippetExpression.  It took a few minutes thought, and a minor refactoring, but I’ll sleep that much better at night. 

Vive le DOM!

Tuesday, 27 June 2006 13:10:37 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, 26 June 2006

A few days back, Jeff commented that he wasn’t convinced about the value of putting an object model on top of what should be simple string generation.  His example was using XmlTextWriter instead of just building an XML snippet using string.Format. 

I got similar feedback internally last week when I walked through some of my recent CodeDOM code.  I was asked why I would write

CodeExpression append = new CodeMethodInvokeExpression(sb,"Append", new CodePrimitiveExpression(delim1));

instead of

CodeExpression append = new CodeSnippetExpression(“sb.Append(delim1)”);

It’s a perfectly reasonable questions.  I’m using the CodeDOM’s object model, but the reality is since we’re an all-C# shop, I’m never going to output my CodeDOM-generated code as VB.NET or J#.  So I could just as easily using a StringBuilder, and a bunch of string.Format calls to write C# code and compile it using the CodeDOM’s C# compiler.  It certainly would be simpler. 

The same is true (as Jeff points out) for XML.  It’s much easier to write XML using string.Format, or a StringBuilder. 

If nothing else, I personally find that using the object-based interface makes me think harder about the structure I’m creating.  It’s not really much less error-prone that writing the code (or XML) by hand, it just provides a different way to screw up.  What it does do is force you to think at a higher level of abstraction, about the structure of the thing you are creating rather than the implementation.  You may never need to output binary XML instead of text, but using XmlTextWriter brings you face to face with the nauances of the structure of the document you’re creating.  Writing a CDATA section isn’t the same as writing an element node.  And it shouldn’t be.  Using the object interface makes those distinctions more obvious to the coder. 

However, it’s definitely a tradeoff.  You have to put up with a lot more complexity, and more limitations.  There are a buch of contructs that would be much easier to write in straight C# than to express them in CodeDOM.  It’s easy to write a lock{} construct in C#, but much more complex to create the necessary try/catch and monitor object using the CodeDOM. 

I was, in fact, forced to resort to the CodeSnippetExpression in one place, where nothing but a terniary operator would do.  I still feel guilty.  :-)  Maybe it just comes down to personal preference, but I’d rather deal with the structure than the syntax even if it means I have to write more complicated code.

Monday, 26 June 2006 14:05:19 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  | 
# Thursday, 22 June 2006

I’m a huge fan or runtime code generation.  I think it solves a lot of common problems in modern applications.  However, the .NET implementation of runtime code gen, a.k.a. the CodeDOM, is viciously difficult to learn and use.  I think that’s holding many people back from implementing good solutions using runtime codegen. 

For example, it takes all this

CodeConditionStatement ifArrayNotNull = new CodeConditionStatement(

    new CodeBinaryOperatorExpression(propertyRef,

    CodeBinaryOperatorType.IdentityInequality,

    new CodePrimitiveExpression(null))

    );

CodeMethodInvokeExpression convertExpr = new CodeMethodInvokeExpression(

    new CodeTypeReferenceExpression(typeof(Convert)),"ToBase64String",

    new CodeExpression[] { new CodeCastExpression(typeof(byte[]),propertyRef)}

    );

ifArrayNotNull.TrueStatements.Add(convertExpr);

to make this

if(myObject.Property != null)

{

    Convert.ToBase64String(myObject.Property);

}

Not only is it a lot more code using the CodeDOM, but it’s certainly not the kind of code that you can just pick up and understand. 

There must be an easier way.  Refly helps a bunch, but last time I tried it I found it to be incomplete.  It’s certainly a step in the right direction.  It’s certainly a model that’s much easier to understand.  I wonder if, in the end, it’s too limiting?  There may be a good reason for the complexity of the CodeDOM.  Or there may not be.

Thursday, 22 June 2006 16:32:32 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  | 
# Monday, 08 May 2006

I’ve been doing some CodeDOM work in the last week or so after not having done it much in a while.  What I’m finding most difficult is keeping track of which constructs are usable and which aren’t.  Being a C# programmer, I tend to think about the code that way.  The hardest part about using the CodeDOM is upleveling your thinking to deal with meta-programming.  Describing the construct you want in the constructs of the CodeDOM can be challenging.

Given all that, I can understand why there are no CodeDOM constructs for foreach, using, lock, etc.  Those are C# language constructs that expand to some other CLR goo.  But ,while?  There’s no way to make a while construct in CodeDOM.  ????  I’m pretty sure there’s nothing language specific about a do…while construct.  So you have to translate into a for…next instead.  Sigh.  I’m glad I don’t have to deal with delegates for this code.  That’d be a third level abstraction, which is more than I can handle…

Monday, 08 May 2006 13:09:00 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  | 
# Wednesday, 06 April 2005
G#

I’m a bit late picking up on this, but if you are interested in either code generation, AOP, or both, check out the spec for G#Ernest Booth has come up with a very interesting spec for a new language that extends C# with some built in constructs for doing code generation.  Since these generators are extensible, etc. this provides not only some great opportunities for code gen (which I do a lot of at work) but for what essentially becomes compile time AOP.  I’ve looked a couple of times at the possibilities for doing AOP in .NET, and most of the options haven’t really been satisfactory (mostly involving remoting contexts).  This would provide most of the benefits of AOP, but happen at compile time in a happy, type-safe kinda way. 

I’ll be very interested to see if this spec turns into actual code.

Wednesday, 06 April 2005 10:09:28 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, 13 May 2004

This is a bit convoluted, but stick with me...

We've got a fairly involved code generation process that builds C# classes from XSDs, which is all well and good.  The code generations uses some utility classes to help with reading the schema files, and those have unit tests, which is cool.  The code generation happens as part of our regular build, so if I screw up the CodeSmith tempate such that the code generation fails, I'll know about it at build time.  If I screw up the CodeSmith template such that the code generation succeeds, but the results don't compile, I'll also find out about that at build time. 

However, since the whole build/codegen process takes a while, it's not the kind of thing you want to run all the time after every change (as is the XP way).  So, how do I unit test the generated classes?  I think I have a workable solution, but it took some thinking about. 

I ended up writing a set of unit tests (using NUnit) that run the code generation process on a known schema.  The resulting C# file is then compiled using the CodeDom, then I can test the resulting class itself.  As a happy side benefit, I'll know if the CodeSmith template runs, and if the resulting C# compiles without having to run the whole build process.  Pretty cool.

An interesting side note: one of the things we do with our generated classes is serialize them as XML using the XmlSerializer.  I discovered during this process that if you generate an assembly with the CodeDom, you can't use the XmlSerializer on the resulting classes unless you write the assembly to disk.  I was using an in-memory only assembly, and the XmlSerializer gave me a very helpful exception stating that the assembly must be written to disk, which was easy enough to do.  I'm assuming that this is because the XmlSerialzer itself is going to generate another dymanic assembly, and it needs something to set it's reference to.  Interesting.

Thursday, 13 May 2004 15:18:08 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, 27 April 2004

As previously mentioned, Scott and I are working on some pretty cool stuff involving generating code from XML Schema, and then doing various bits of stuff to those generated objects.  Today what I'm pondering is not the code generation part per se, but the bits of stuff afterwards part. 

For example, if you want to take your generated class and serialize it as a string, there are (at least) three options:

  • Generate the serialization code as part of the code generation itself.  E.g. code gen the objects .ToString() method at the same time as the rest of the code.
  • Insert some cues into the object at code gen time, in the form of custom attributes, then reflect over the object at runtime and decide how to serialize it.
  • Insert some cues into the object at code gen time, in the form of custom attributes, then reflect over the object once at runtime and dynamically build the serialization code, which can then be cached (a la the XmlSerializer).

The advantage to number one is that it's fairly easy to understand, the code is pretty easy to generate, and the resulting code is probably the most performant.  The disadvantages are that the code embedded in the code gen process is a bit harder to maintain, since it's "meta-code", and that if you want to support different serialization formats for the same object, you might have to generate quite a lot of code, which embeds a lot of behavior into the objects.  That may not be a bad thing, since the whole point is that you can always regenerate the objects if the serialization behavior needs to change.

The advantage to number two is that it is the most flexible.  The objects don't need to know anything at all about any of the formats they might be serialized into, with the exception of having to be marked up with any appropriate custom attributes.  You can add new serialization methods without having to touch the objects themselves.  The biggest drawback (I think) is the reliance on reflection.  It's hard for some people to understand the reflection model, which might make the code harder to maintain.  Also, there are theoretical performance issues with using reflection all the time (many of which would be solved by #3) although we've been running this code in production and it's performing fine, but that's no guarantee that it always will.  Scott is also a bit concerned that we may run into a situation where our code isn't granted reflection privileges, but in that case we'll have plenty of other problems to deal with too.  As long as our code can be fully trusted I don't think that's a big issue.

The advantage to number three is essentially that of number two, with the addition of extra performance at runtime.  We can dynamically generate the serialization code for each object, and cache the compiled assembly just like the XmlSerializer does.  The biggest disadvantages are that it still leaves open the reflection permission isse, and (first and foremost) it's a lot more work to code it that way.  Like #1, you end up writing meta-code which takes that extra level of abstraction in thinking about.

Practically speaking, so far I find #1 easier to understand but harder to maintain, and #2 easier to maintain but much harder to explain to people. 

If anyone has any opinions or experiences I'd love to hear them.

Tuesday, 27 April 2004 10:39:53 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |