【问题标题】:Dealing with concurrency and complex WCF services interacting with objects of the overall application处理与整个应用程序的对象交互的并发和复杂的 WCF 服务
【发布时间】:2011-05-17 11:33:13
【问题描述】:

我喜欢创建和托管 WCF 服务。 到目前为止,我可以创建服务,定义服务和数据(接口)的合同,并定义主机和配置选项以达到它们(端点规范)。

好吧,考虑一下这段代码定义一个服务并使用它(这里没有提到 app.config 中定义的端点,这里没有显示):

[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();
      }
   }
}

嗯,这种结构在创建可以称为独立服务的东西时非常有用。 如果我需要我的服务来使用更大应用程序的对象怎么办。 例如,我需要一项服务,该服务基于我的程序中某处定义的某个集合(托管该服务)来执行某些操作。服务必须查看此集合并搜索并返回特定元素。

我说的列表是由程序管理并由它编辑修改的列表。

我有以下问题:

1) 如何构建能够处理此列表的服务? 我知道一个可能的选择是使用重载的ServiceHost 构造函数接受Object 而不是Type 服务。 所以我可以在那里传递我的清单。好吃吗?

[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)
      }
   }
}

这个例子应该澄清。 这是做的好方法吗?我做得对吗?

2) 如何处理我的服务和我的应用程序之间的共享资源冲突? 当我的应用程序运行并托管服务时,我的应用程序可以在列表中插入项目并删除它们,服务也可以这样做。我需要互斥体吗?如何处理? 请注意,并发问题涉及两个参与者:主应用程序和服务。服务确实是单例的,但应用程序在列表中起作用!!! 我假设该服务是由外部实体调用的,当这种情况发生时,应用程序仍然可以运行吗?这种情况下有并发吗???

谢谢

【问题讨论】:

  • 在第 1 点上,构造函数用于创建单例服务。 ServiceHost 将仅包含该实例。当然,如果你这样做,它肯定会解决 #2 中的任何问题 ;-)
  • 拜托大家在编辑中发现变化
  • 编辑了我的帖子。 @Sixto 对维护/修改您的单例方法有很好的建议,但实际上我相信您正在尝试实现 Sessions 的等效性。

标签: c# .net wcf concurrency


【解决方案1】:

关于第 2 点,您可以使用Concurrent Collections 来管理所需的大部分线程安全。

我不确定您所说的第 1 点是什么意思。听起来您在描述基本的polymorphism,但也许您可以举个例子来澄清一下?

编辑:针对您对 Sixto 的回答所做的 cmets,请考虑使用 WCF 的 sessions。根据您的描述,在我看来,WCF 服务应该位于单独的主机应用程序上。您当前使用的应用程序应该具有对该服务的服务引用,并且使用会话将能够调用一个操作来模仿您使用当前客户端应用程序定义的列表来实例化服务的要求。

将此与我对公开允许与此列表交互的操作的评论结合起来,您将能够运行多台客户端计算机,处理会话存储的列表?

希望解释得足够清楚。

【讨论】:

    【解决方案2】:

    将构造函数添加到 MyService 以传递列表肯定会按您的预期工作。然而,就像我在对问题的评论中所说的那样,ServiceHost 永远包含 MyService 类的单个实例,因此不会共享该列表,因为只有一个服务实例会使用它。

    我会查看dependency injector (DI) container,让 WCF 来做你想做的事情。让 DI 容器为您的服务提供单例列表实例。 @Smudge202 也绝对正确,使用并发收集功能是实现列表所需要的。

    基于 cmets 线程的更新:

    DI 方法的工作原理是从 DI 容器中获取对象的所有依赖项,而不是在代码中手动创建它们。您注册将由容器提供的所有类型作为应用程序启动的一部分。当应用程序(或 WCF)需要一个新的对象实例时,它会从容器中请求它,而不是“更新”它。例如,Castle Windsor WCF integration library 实现了从容器中提供 WCF 服务实例所需的所有布线。如果您想推出自己的 WCF 集成,请将此 posts explains the details of how to use the Microsoft Unity DI container 与 WCF。

    此问题中引用的共享列表将在容器中注册为您的应用程序中已实例化的对象。当从 DI 容器启动 WCF 服务实例时,将提供所有构造函数参数,包括对共享列表的引用。有很多关于依赖注入和控制反转的信息,但this Martin Fowler article 是一个很好的起点。

    【讨论】:

    • 我知道创建了一个服务实例,但无论如何我都有一个共享资源。它由我的应用程序和服务共享,请考虑问题中的编辑:)
    • Singleton 通常不是 WCF 的一个好的使用模式,因为它会扼杀可伸缩性(从而扼杀并发性)。我不相信您所描述的场景是单例服务的有效理由。例外情况是,如果应用程序托管的服务预计不会被频繁地同时调用(如果有的话)。如果您希望您的服务能够处理并发客户端,那么 DI 容器方法是最佳解决方案。
    • 刚刚看到你的第二条评论。如果按照@Smudge202 描述的方式实现,服务和应用程序可以同时访问和更新列表。 WCF 服务配置(单例与否)的问题取决于服务客户端是否需要并发处理。共享列表要求不会以某种方式影响此决定。在任何一种情况下,服务实例或实例都会收到对共享列表的引用。
    • 最好将最后一条评论添加为新问题。单独托管服务(在您当前的应用程序之外)。将服务的服务引用添加到您当前的应用程序中。公开服务合同上的操作,允许操纵您希望共享的任何资源。 (即在合约上提供AddToList、GetFromList、RemoveFromList)
    • 还应该提到,我说的是服务引用,因为您可以轻松地异步调用服务或以您认为合适的任何方式调用服务(选中服务引用属性上的“生成异步...”复选框页)。
    猜你喜欢
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 2013-07-26
    • 1970-01-01
    • 2014-01-01
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多