Home > .net, servicemodelex, wcf > Flickr WCF Part II - Hosting WCF Components In-Process

Flickr WCF Part II - Hosting WCF Components In-Process

February 16th, 2009

This is Part Two in an on-going series of articles about WCF components, all centered around a simple component I created to talk to the Flickr api. You can find Part I here.

Now that we’ve hosted the Flickr WCF component in IIS, let’s take the same service definition and implementation and do something more interesting with them than just spitting out a list of URLs. It would be cool if we could see each of the pictures and cycle through them. And, so that I can point out a potential WCF gotcha, let’s do this in a WinForms application.

Let’s also host the component in process. In process components should always use named pipes. I’ve found that the easiest possible way to host a component in process is by using Juval Lowy’s ServiceModelEx library. You can download the library at this link. We’ll use his InProcFactory class which he describes in some detail on pages 60-63 of his WCF Bible, “Programming WCF Services.”
With InProcFactory all you need to do is to add references to the class libraries which contain your component’s contracts and implementation.

Then you can make calls like this:


IMyContract proxy = InProcFactory.CreateInstance<MyService, IMyContract>();
proxy.MyMethod();
InProcFactory.CloseProxy(proxy);

Notice that when we use InProcFactory we don’t have to worry about setting up hosts, config files, or really worry about anything other than our interfaces and implementation classes. This is almost as easy creating regular c# objects with the new keyword! Using named pipes is also the fastest and most secure way to deal with WCF components.

So, for this example, let’s create a new Windows Forms Application and name it WCFInProcFlickrApp. Add references to your BasicFlickrWCFContracts and FlickrInfoService dlls as well as Juval Lowy’s ServiceModelEx library.

Add a new Form and call it Viewer. Add a PictureBox (picBox) and two buttons (btnNext and btnPrev). Make your form look like this:

Now let’s make sure that we can connect to our WCF component without any problems. Double click the View form and then add code to the Viewer_Load method that looks like this:


        private void Viewer_Load(object sender, EventArgs e)
        {

            IFlickrInfo proxy = ServiceModelEx.InProcFactory.CreateInstance<FlickrInfoService, IFlickrInfo>();

            photos = proxy.GetRecentPhotos();

            ServiceModelEx.InProcFactory.CloseProxy(proxy);

            picBox.ImageLocation = photos[0].Url;
        }

Now try running the app. When you run this you should expect the picture box to show the first image returned by component. Instead the application hangs for a long time and eventually you’ll get an error message that looks like this:

The problem here is that we’ve hosting the component in-process after the UI thread has started. This causes the component to run on the UI thread associated with the form. The UI thread’s message loop acts as a throttle for message processing. When the form calls the service in-process like this that call blocks the UI thread while WCF posts a message to the UI thread to invoke the service. We’re stuck in a loop now because of the blocking UI thread and hence we end up with this deadlock shown in the error above.

The problem is that WCF components have the UseSynchronizationContext attribute set to true by default. When this behavior is set to true, the component gains thread affinity with the code that called it. In our WinForms app this makes a big difference because of the message loop. One really simple way to fix this would be to decorate our implementation class with the following attribute which sets that context to false:


[ServiceBehavior(UseSynchronizationContext=false)]

This removes the thread affinity and lets our component run on its own thread, eliminating the blocking and deadlock issue. In this example I don’t want to go this route, because I’ve already created my component and it works just fine. I would only be adding this attribute to help it work in this one case. This is starting to smell like coupling, which I try to avoid if at all possible. Either way, now that my contracts and implementation are in dlls, I don’t want to have to go and recompile them just to get them to work for WinForms. There’s got to be another way.

Fortunately there is. All we need to do is to start hosting the component before the UI thread is set. To do this, we need to create the host in the Main method that starts the WinForms app. This method can be found in the Program.cs file in the solution. Now we run into another problem. The way that Lowy wrote InProcFactory, the service host is created, if needed, when you make the call to CreateInstance. If I put this call in the Main method then I’ll need something like a global variable to hook into in my Viewer form that would be of no use to other forms in my project. That’s a pretty stinky code smell too.

To solve this issue, I created a new static method on InProcFactory - CreateHost. The method is as follows:


      public static void CreateHost<S, I>()
          where I : class
          where S : class, I
      {
          if (m_Hosts.ContainsKey(typeof(S)))
          {
              return;
          }

          HostRecord hostRecord;
          ServiceHost host;

          if (m_Singletons.ContainsKey(typeof(S)))
          {
              S singleton = m_Singletons[typeof(S)] as S;
              Debug.Assert(singleton != null);
              host = new ServiceHost(singleton, BaseAddress);
          }
          else
          {
              host = new ServiceHost(typeof(S), BaseAddress);
          }

          string address = BaseAddress.ToString() + Guid.NewGuid().ToString();
          hostRecord = new HostRecord(host, address);

          m_Hosts.Add(typeof(S), hostRecord);

          host.AddServiceEndpoint(typeof(I), Binding, address);          

          if (m_Throttles.ContainsKey(typeof(S)))
          {
              host.SetThrottle(m_Throttles[typeof(S)]);
          }

          host.Open();
      }

This is almost a verbatim copy and paste of the GetHostRecord method that’s already in ServiceModelEx. Yes, I can and should refactor out the similarities, but for the purposes of this article I think it’s helpful to see what’s going on. CreateHost creates a new Named Pipe in-proc host just like CreateInstance does. Since it’s a static method on a static class, the host will stick around after the Viewer form is created. When CreateInstance is called, InProcFactory will see that our host has already been created and will use that one. In this way we don’t gain thread affinity with the UI thread.

So now, change the code in the Main method inside Program.cs to look like this:


        [STAThread]
        static void Main()
        {
            InProcFactory.CreateHost<FlickrInfoService, IFlickrInfo>();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Viewer());
        }

You can now run the application again and you should see the first picture returned back in the picture box. To round out our little app, hook in the buttons click events (by double clicking each of them) and then add code to them like this (as well as adding the ShowCurrentImage method):


        private void btnNext_Click(object sender, EventArgs e)
        {
            currentIndex++;
            if (currentIndex > 99)
            {
                currentIndex = 0;
            }
            ShowCurrentImage();
        }

        private void ShowCurrentImage()
        {
            picBox.ImageLocation = photos[currentIndex].Url;
        }

        private void btnPrev_Click(object sender, EventArgs e)
        {
            currentIndex--;
            if (currentIndex < 0)
            {
                currentIndex = 99;
            }
            ShowCurrentImage();
        }

Now you can use the Next and Prev buttons to cycle through all of the interesting photos returned back from Flickr! The part about all of this that I like the most is that we didn’t have to change our component at all in order to do any of this. Hurray for component reuse!

All of this same information can be used in WPF applications as well. I’m not really familiar with WPF applications, but I understand you can configure your WPF application to use a custom Main method by right-clicking the App.xaml file, selecting Properties, and setting the Build Action to “Page.” Now create a static class Program.cs in the root and insert a Main() method like this:


public static class Program
{
    [STAThread]
    static void Main()
    {
        WPFClient.App app = new WPFClient.App();
        app.InitializeComponent();
        app.Run();
    }
}

I haven’t actually tried this, but if you have any problems with this method in WPF, please leave a comment below and I’ll do some research for you.

Here’s a copy of my WCFInProcFlickrApp source.

Here’s a copy of my enhanced version of ServiceModelEx.

REFERENCES:
For a much better explanation of InProcFactory, please see “Programming WCF Services” pages 60-63.
Programming WCF Services” - Chapter 8 pages 388 through 413 were very helpful.
Peter De Jonghe’s post on the MSDN WCF forums.
Jeremy Wiebe’s “WCF service blocking when self-hosting (or How the ServiceBehavior’s Use SynchronizationContext parameter saved me)
Code Magazine’s article about WCF Hosting, Page 3

Tad .net, servicemodelex, wcf , , ,

Viewing 3 Comments

 

Trackbacks

(Trackback URL)

close Reblog this comment
blog comments powered by Disqus
Clicky Web Analytics