0

I am trying to take my first steps into IPC and the WCF, and so far, I'm falling flat on my face. I have a Winforms application that I would like to instrument somewhat for remote callers. The winforms application has most of its business logic confined to a singleton that takes care of all the background work. I would like to expose some of the functionality through an IPC mechanism. WCF seems like the way forward, so I started out with that.

What I tried is adding a WCF Service Library project to my solution, through which I would like to expose some calls. When I start the Winforms project in the VS debugger, it runs as normal, and the WcfSvcHost starts up. I can communicate to the WCF service with the WcfTestClient.

However, when I try to access the singleton holding the code I would like to communicate with, it seems like I am getting a new singleton object. Clearly, I'm doing it wrong; what I guess is happening is that the service runs in a different process, so there is no real shared code, and hence no shared singleton.

I'm not sure how I should continue. Is my choice of using WCF for IPC the wrong one? Should I integrate the WCF endpoints in the Winforms application? Is what I'm trying even feasible?

EDIT: I figured this was so high-level, and also so simple that any code sample would be useless. I think I was wrong. So some code:

In the WinForms assembly:

public partial class Form1 : Form
{
  public Form1()
    {
      InitializeComponent();
      label1.Text = MySingleton.Instance.InitedAt.ToString();
    }
}

public class MySingleton
{
  private static MySingleton instance = new MySingleton();
  private DateTime inited;

  private MySingleton()
  {
    this.inited = DateTime.Now;
  }

  public static MySingleton Instance
  {
    get
    {
      return instance;
    }
  }

  public DateTime InitedAt
  {
    get
    {
      return this.inited;
    }
  }
}

In the WCFServiceLibrary assembly:

[ServiceContract]
public interface IApplicationProbe {

  [OperationContract]
  string DoesItWork();

  [OperationContract]
  string SingletonInited();
}

public class ApplicationProbe : IApplicationProbe {
  public string DoesItWork(){
    return "Why yes, yes it does";
  }

  public string SingletonInited(){
    return MySingleton.Instance.InitedAt.ToString();
  }
}

when I query SingletonInited through the WcfTestClient, I get an InitedAt which is not the same DateTime as the instatiation of the winforms singleton.

Edit2:

I have this code running as is (with the auto-generated scaffolding around the Winforms stuff). The label on the form displays a different time than the time returned from the WCF call, demonstrating it is a different instance.

Martijn
  • 11,964
  • 12
  • 50
  • 96
  • IPC with WCF is usually done with named pipes. It's certainly supported; but there's lots of overhead. There's much more performant ways of doing IPC other than WCF. Memory-mapped files, for example. – Peter Ritchie Jul 26 '12 at 15:50
  • Did you mean WCF instead of WPF? This is a first setup: First get it to work, then get it to work efficiently. Since I can't get the first step to work just yet, I haven't come around to the second yet, but I figured Named Pipes would be a good candidate. I'll look in to memory mapped files, thanks for the suggestion. – Martijn Jul 26 '12 at 15:52
  • Yes, WCF, not WPF... autocorrect :) – Peter Ritchie Jul 26 '12 at 15:53
  • Since this is not primarily about large amouts of data exchange, but more about letting the application on the other side do some amount of lifting/work, MMFs bare metal style seems less suitable than the more managed/typesafe WCF for me. – Martijn Jul 26 '12 at 16:03

2 Answers2

1

I assume you're using your singleton class as a service (it implements a contract). I suggest you develop a WCF contract and a service, which will make calls to your singleton instead.

So you'll have something like this:

public class YourImpportantSingleton
{
    public YourImpportantSingleton Instance { get; set; }
    public void DoSeriousBusiness(){...}
}

[ServiceContract]
public interface IYourContract
{
    void YourRemoteAction();
} 

public class YourService : IYourContract
{
    public void YourRemoteAction()
    {
        YourImportantSingleton.Instance.DoSeriousBusiness();
    }
}

UPD: Ok, just realized, that you might not be using self-hosting in a winforms application, sorry for that waste of time.

Your options would be then either host a service with ServiceHost in your forms application or host a service separately (with IIS, for example) and make this service a keeper of your singleton. You'll have to change your forms application to call separate service, as it holds the state now, of course.

Dmitriy
  • 1,852
  • 4
  • 15
  • 33
  • I added some code for what I have now, which looks eerily like yours – Martijn Jul 26 '12 at 14:45
  • @Martijn, then WCF won't create second instance of your singleton (you forgot `static`'s, by the way), but it will create instace(s) of your service class. – Dmitriy Jul 26 '12 at 14:49
  • I forgot the statics here, just fixed them. I'm going to run my example code, i'll let you know what happens. Thanks for looking in to it! – Martijn Jul 26 '12 at 14:51
  • In your particular example InitedAt will be set to the first singleton access time, because w/out static constructor present `static` fields will be initialized lazily. – Dmitriy Jul 26 '12 at 14:52
  • I completed the code and have it running. (I can quickly put the whole solution tree on the web if you want so you can verify). The WCF call shows a different time than the label on the form shows – Martijn Jul 26 '12 at 15:18
  • Ok, I hoped a problem was really trivial. Can you share a way you setup your service? – Dmitriy Jul 26 '12 at 15:26
0

The problem here was that WCF Service Host was hosting the service, rather than the application itself. This caused the application to run in a seperate ApplicationDomain, which in turn caused a new singleton to be created. Switching to self-hosting solved the problem.

Martijn
  • 11,964
  • 12
  • 50
  • 96