简体   繁体   中英

Dealing with concurrency and complex WCF services interacting with objects of the overall application

I am enjoying creating and hosting WCF services. Up until now I can create services defining contracts for the service and data (interfaces) and defining hosts and configuration options to reach them (endpoint specifications).

Well, consider this piece of code defining a service and using it (no mention for endpoints that are defined in app.config not shown here):

[ServiceContract]
public interface IMyService {
   [OperationContract]
   string Operation1(int param1);
   [OperationContract]
   string Operation2(int param2);
}

public class MyService : IMyService {
   public string Operation1(int param1) { ... }
   public string Operation2(int param2) { ... }
}

public class Program {
   public static void Main(stirng[] args) {
      using (ServiceHost host = new ServiceHost(typeof(MyService))) {
         host.Open();
         ...
         host.Close();
      }
   }
}

Well, this structure is good when creating something that could be called a Standalone service. What if I needed my service to use objects of a greater application. For example I need a service that does something basing on a certain collection defined somewhere in my program (which is hosting the service). The service must look into this collection and search and return a particular element.

The list I am talking about is a list managed by the program and edited and modified by it.

I have the following questions:

1) How can I build a service able to handle this list? I know that a possible option is using the overloaded ServiceHost constructor accepting an Object instead of a Type service. So I could pass my list there. Is it good?

[ServiceContract]
public interface IMyService {
   [OperationContract]
   string Operation1(int param1);
   [OperationContract]
   string Operation2(int param2);
}

public class MyService : IMyService {
   private List<> myinternallist;
   public MyService(List<> mylist) {
      // Constructing the service passing the list
   }
   public string Operation1(int param1) { ... }
   public string Operation2(int param2) { ... }
}

public class Program {
   public static void Main(stirng[] args) {
      List<> thelist;
      ...
      MyService S = new MyService(thelist)
      using (ServiceHost host = new ServiceHost(S)) {
         host.Open();
         ...
         host.Close();
         // Here my application creates a functions and other that manages the queue. For this reason my application will edit the list (it can be a thread or callbacks from the user interface)
      }
   }
}

This example should clarify. Is it the good way of doing? Am I doing right?

2) How to handle conflicts on this shared resource between my service and my application? When my application runs, hosting the service, my application can insert items in the list and delete them, the same can do the service too. Do I need a mutex? how to handle this? Please note that the concurrency issue concerns two actors: the main application and the service. It is true that the service is singleton but the application acts on the list!!! I assume that the service is called by an external entity, when this happens the application still runs right? Is there concurrency in this case???

Thankyou

Regarding point 2, you can use Concurrent Collections to manage most of the thread safety required.

I'm not sure what you mean by point 1. It sounds like you're describing basic polymorphism , but perhaps you could clarify with an example please?

EDIT: In response to comments you've made to Sixto's answer, consider using WCF's sessions . From what you've described it sounds to me like the WCF service should be sat on a seperate host application. The application you are using currently should have a service reference to the service, and using sessions would be able to call an operation mimicking your requirement for instantiating the service with a list defined by the current client application.

Combine this with my comment on exposing operations that allow interaction with this list, and you'll be able to run multiple client machines, working on session stored Lists?

Hope that's explained well enough.

Adding the constructor to MyService for passing the list certainly will work as you'd expect. Like I said in my comment to the question however, the ServiceHost will only ever contain a single instance of the MyService class so the list will not be shared because only one service instance will consume it.

I would look at a dependency injector (DI) container for WCF to do what you are trying do. Let the DI container provide the singleton list instance to your services. Also @Smudge202 is absolutely correct that using the Concurrent Collection functionality is what you need to implement the list.

UPDATE based on the comments thread:

The DI approach would works by getting all of an object's dependencies from the DI container instead of creating them manually in code. You register all the types that will be provided by the container as part of the application start up. When the application (or WCF) needs a new object instance it requests it from the container instead of "newing" it up. The Castle Windsor WCF integration library for example implements all the wiring needed to provide WCF a service instance from the container. This posts explains the details of how to use the Microsoft Unity DI container with WCF if you want to roll your own WCF integration.

The shared list referenced in this question would be registered in the container as an already instantiated object from your application. When a WCF service instance is spun up from the DI container, all the constructor parameters will be provided including a reference to the shared list. There is a lot of information out there on dependency injection and inversion of control but this Martin Fowler article is a good place to start.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM