【问题标题】:How do I create a property that all sessions in a WCF service have access to?如何创建 WCF 服务中的所有会话都可以访问的属性?
【发布时间】:2012-10-31 08:00:17
【问题描述】:

我有 nettcpbinding 服务并使用 windows 服务托管它。该服务必须在网络上运行,并且它处理来自 100 多个客户端的传入消息。

问题: 我想要一个所有会话都可以访问的属性。像这样:

class a
{
   list<string> strList=new list<string>();

class b{}
class c{}
...
}

在本例中,所有类都可以访问 strList。我想要一个所有会话都可以访问的列表(在该列表中添加或删除东西)。

服务配置是缓冲的,没有安全性。和服务属性在这里:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
[ServiceContract(SessionMode = SessionMode.Required)]

编辑: 我不想创建只是一个示例的类。我只需要一个所有会话都可以访问它的列表。当您拥有 InstanceContextMode.PerSession 服务时,该服务类将为每个客户端创建,然后每个客户端都有自己的服务类,现在我希望创建的每个会话都可以访问一个公共列表。

EDIT2: 此列表在服务器中,只有服务器可以访问它,不需要将列表发送给客户端。它是计算某些东西的服务器变量。

【问题讨论】:

    标签: c# wcf service windows-services nettcpbinding


    【解决方案1】:

    您可以在服务类中使用静态属性,例如:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    [ServiceContract(SessionMode = SessionMode.Required)]
    public class MyService : IMyService {
    
        // this is your static data store which is accessible from all your sessions
        private static List<string> strList = new List<string>();
    
        // an object to synchronize access to strList
        private static object syncLock = new object();
    
        public void AddAction(string data) {
    
            // be sure to synchronize access to the static member:
            lock(syncLock) {
                strList.Add(data);
            }
        }
    
    }
    

    WCF 将为连接到您的服务的每个新客户端创建一个新的 MyService 实例。 他们都可以访问静态属性。

    【讨论】:

      【解决方案2】:

      您可能希望您的 ConcurrencyMode 设置为 Multiple,并且您需要确保将您的对象视为多线程,因为这就是您基本设置的内容。在这种需要多重锁定的情况下,有一种模式可以避免死锁。见This MSDN article for details

      [SerivceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
      class MyService : IMyContract
      {
      
      //Here is your shared object
      static List<string> _strList = new List<string>();
      
      //Only access the property for thread safety, not the variable
      static List<string> StrList
      {
          get
          {
              lock(typeof(MyService)
              {
                  return _strList;
              }
          }
          set
          {
              lock(typeof(MyService)
              {
                  _strList = value;
              }
          }
      }
      
      void DoSomeThing()
      {
          lock(typeof(MyService))
          {
              //Do something with your list here, other threads are blocked from accessing
              // objects in lock
              StrList.Add("Something");
          }
      }
      }
      

      如果您正在考虑使用集合,我建议您查看Concurrency Collection 对象,因为这些对象是为多线程访问而设计的。这些对象不需要锁定,因为它们具有自包含锁定,这在您将来忘记的情况下很好。

      编辑:只是为了补充信息,锁定将阻止其他线程执行该锁定中的代码或访问锁定的属性。出于这个原因,不建议在锁中进行冗长的操作,因为它会减慢所有客户端的速度。此外,您的 InstanceContextMode 设置为 PerCall 将为您的服务的每次调用创建一个新的服务类实例。相反,如果您没有任何活动并且您的所有服务实例都被清理或关闭,那么您也将丢失您的共享对象。

      【讨论】:

      • 感谢您的回答,我投了赞成票,但我认为我的回答是 jan 回答
      【解决方案3】:

      我认为你应该建立一个 DataContract

      例子:

        [DataContract]
          public class A
          {
           [DataMember]
           list<string> strList { get; set; }
      
           class B
             {
             }
      
           class C
             {
             }
         }
      

      【讨论】:

      • 这样您就可以构建一个 ServiceContract 以将该列表返回给客户端?
      猜你喜欢
      • 2023-04-10
      • 2012-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-28
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多