The Problem Solver

Tell me and I will forget
Show me and I will remember
Involve me and I will understand
- Confucius -

Google Ads

This Blog

Syndication

Search

Tags

News





  • View Maurice De Beijer's profile on LinkedIn

Community

Email Notifications

Explore

Archives

July 2007 - Posts

One of the nifty features in Windows Communication Foundation is duplex requests. To define a duplex request you need to create two interfaces, both with their OperationContract marked with IsOneWay:=True. The request interface also contains a CallbackContract with the response interface.

<ServiceContract(CallbackContract:=GetType(IDuplexResponse))> _

Public Interface IDuplexRequest

    <OperationContract(IsOneWay:=True)> _

    Sub SendRequest(ByVal data As String)

End Interface

   

<ServiceContract()> _

Public Interface IDuplexResponse

    <OperationContract(IsOneWay:=True)> _

    Sub SendResponse(ByVal data As String)

End Interface

 

Now in the request implementation you can use the OperationContext to retrieve the callback interface using OperationContext.Current.GetCallbackChannel(Of IDuplexResponse)().

Public Class DuplexRequest

    Implements IDuplexRequest

   

    Public Sub SendRequest(ByVal data As String) Implements IDuplexRequest.SendRequest

        Dim responseChannel As IDuplexResponse = OperationContext.Current.GetCallbackChannel(Of IDuplexResponse)()

        responseChannel.SendResponse(String.Format("I received '{0}'.", data))

    End Sub

End Class

 

So far so good. Now with all the operations marked as one way and seem a perfect fit for a netMsmqBinding implementation. Unfortunately this doesn't seem to work though, or otherwise I could not figure out how to get this to work Sad. Even though all operations are one way the channel still needs to be a duplex channel and as the netMsmqBinding is a simple binding instead of a duplex binding this just doesn't work.

This is unfortunate because the sample Microsoft released showing duplex communication is very primitive and in fact strongly coupled to netMsmqBinding as it requires passing the address as a normal piece of data to the client. Because of this it doesn't seem to be in the "spirit" of WCF Sad. BTW you can find the Microsoft sample at: http://msdn2.microsoft.com/en-us/library/ms752264.aspx.

If anyone has OperationContext.Current.GetCallbackChannel() working with netMsmqBinding I would appreciate the information on how to do this.

 

Posted by Maurice | 1 comment(s)
Filed under: , ,

Most of the time there isn't much of a problem when developing custom activities and workflow persistence. After all when an external system send a message, the service retrieves this, extracts the WorkflowInstanceId and queue name and signals the workflow. Everything's works just fine and if the workflow runtime restarts the message received will cause the workflow to be reloaded.

However there is a catch. Suppose the external service isn't passively waiting for an external event but must do so in a more active mode. An example of this is a service waiting for a particular file to be recreated. In this case the service needs to be aware of the file we are waiting for even after a restart of the workflow runtime. When the workflow starts and uses a SqlWorkflowPersistenceService each workflow waiting for a DelayActivity is actually reloaded if the delay timer has expired. When this happens an OnActivityExecutionContextLoad() function is called on the activity waiting. This activity can now signal the external service that it is waiting for the file. Adding a dummy timer subscription isn't all that hard.

Activity parent = this;

while (parent.Parent != null)

{

    parent = parent.Parent;

}

   

TimerEventSubscriptionCollection timers = (TimerEventSubscriptionCollection)parent.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty);

TimerEventSubscription item = new TimerEventSubscription(WorkflowInstanceId, DateTime.UtcNow);

timers.Add(item);

 

This code will prevent the requirements for an extra persistence service for use with the runtime service waiting for the file. Keep in mind though that this behavior depends on the internal, and undocumented, behavior of the DelayActivity and the SqlWorkflowPersistenceService so it could well change in the future.

Enjoy!

Posted by Maurice | 2 comment(s)
Filed under: , ,

I am changing my blog to go through FeedBurner in the future. So if you are subscribing to the RSS feed of my blog please update it to point to http://feeds.feedburner.com/TheProblemSolver instead.

Posted by Maurice | with no comments

Caching can be a great way of increasing the performance of an application. I often use the HttpRuntime.Cache just for this purpose, even in WinForm applications as it is fast and easy to use. However as usual there is a tradeoff. In the case of caching the catch is memory consumption. Instead of querying or calculating some data again just keep all results around in the hope they are used again. But that uses up memory and while coding you probably have a fast machine with plenty of memory the case at runtime might be a little different.

One easy way to solve the problem is to the WeakReference object. Using this WeakReference you keep sort of a hold on an object but allow the .NET garbage collector to remove it from memory when required. The following code is a quick sample of how to do this. Keep in mind that this is a quick demo and not fully tested so use at your own risk Smile

using System;

using System.Web;

   

namespace MesFileImporterShared.Utils

{

    static class Cache

    {

   

        static public void Insert(string key, object value)

        {

            CacheItem item = GetCacheItem(key, value);

   

            HttpRuntime.Cache[key] = item;

        }

   

   

        private static CacheItem GetCacheItem(string key, object value)

        {

            CacheItem result = new CacheItem();

            result.Key = key;

            result.Value = new WeakReference(value, false);

            return result;

        }

   

        private static bool Exists(string key)

        {

            bool result = false;

            CacheItem item = HttpRuntime.Cache[key] as CacheItem;

   

            if (item != null)

            {

                result = item.Value.IsAlive;

            }

   

            return result;

        }

   

        public static object Get(string key)

        {

            object result = null;

            CacheItem item = HttpRuntime.Cache[key] as CacheItem;

   

            if (item != null)

                if (item.Value.IsAlive)

                    result = item.Value.Target;

                else

                    throw new NullReferenceException("Item is no longer alive");

   

            return result;

        }

   

        public static bool TryGet(string key, out object value)

        {

            bool result = false;

            value = null;

            CacheItem item = HttpRuntime.Cache[key] as CacheItem;

            if (item != null && item.Value.IsAlive)

            {

                value = item.Value.Target;

                result = true;

            }

   

            return result;

        }

   

        private class CacheItem

        {

            public string Key;

            public WeakReference Value;

        }

    }

}

 

Enjoy!

Posted by Maurice | 1 comment(s)
Filed under:

Dear Maurice de Beijer,

Congratulations! We are pleased to present you with the 2007 Microsoft® MVP Award!

The Microsoft MVP Award is our way of saying thank you and to honor and support the significant contributions you make to communities worldwide. As a recipient of Microsoft's Most Valuable Professional award, you join an elite group of technical community leaders from around the world who foster the free and objective exchange of knowledge by actively sharing your real world expertise with users and Microsoft. Microsoft salutes all MVPs for promoting the spirit of community and enhancing people's lives and the industry's success everyday. To learn more about the MVP Program, visit: www.microsoft.com/mvp.

Your extraordinary efforts in Visual Developer - Visual Basic technical communities during the past year are greatly appreciated.

 

Yes that is right, MVP for another year Smile

Posted by Maurice | 1 comment(s)
Filed under: