【问题标题】:WCF methods sharing a dictionary共享字典的 WCF 方法
【发布时间】:2011-10-18 23:46:21
【问题描述】:

我正在创建一个 WCF 服务库,我有一个关于线程安全使用该库中的方法的问题,这是我到目前为止的完整实现。

namespace WCFConfiguration
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
    public class ConfigurationService : IConfigurationService
    {
        ConcurrentDictionary<Tuple<string,string>, string> configurationDictionary = new ConcurrentDictionary<Tuple<string,string>, string>();

        public void Configuration(IEnumerable<Configuration> configurationSet)
        {
            Tuple<string, string> lookupStrings;
            foreach (var config in configurationSet)
            {
                lookupStrings = new Tuple<string, string>(config.BoxType, config.Size);
                configurationDictionary.TryAdd(lookupStrings, config.RowNumber);
            }
        }

        public void ScanReceived(string boxType, string size, string packerId = null)
        {

        }
    }
}

假设我的 configurationDictionary 中有 10 个值,并且许多人想使用 ScanReceived 方法查询这个字典,这 10 个值是否为请求 ScanReceived 的每个客户端共享?我需要更改我的 ServiceBehavior 吗?

顺便说一句,Configuration方法只供一个人使用。

【问题讨论】:

  • 您的服务具有 ConcurrencyMode.Single,因此您不会遇到并发问题。此外,ScanReceived 没有代码,所以我很确定您可以安全地调用返回 void 的无操作方法。
  • 我仍在处理 ScanReceived 的代码,但它会更改为 int。

标签: c# .net wcf web-services thread-safety


【解决方案1】:

使用InstanceContextModePerCall,您应该在每次远程调用(我假设将是Configuration()ScanReceived())时获得一个新的服务实例和字典。这不会在多个客户端之间共享configurationDictionary

使用ConcurrencyModeSingle,您在任何时候都只会有一个线程运行您的代码。所以任何并发问题都没有实际意义。

两种分享方式configurationDictionary

  1. 设为静态:private readonly static ConcurrentDictionary&lt;...&gt; ...
  2. 更改您的InstanceContextMode,也可能更改您的ConcurrencyMode

如果您不希望每秒调用数千次您的服务,我建议您使用第一个选项。

MSDN 有一些关于InstanceContextModeinstancing 服务类的信息。


如果您更改为InstanceContextMode.SingleConcurrencyMode.Multiple,您可以同时执行多个线程,您需要担心同步访问。

要注意的主要事情是,当您查询/迭代您的字典时,其他人可能会修改它。抓取字典的快照然后查询快照应该可以解决这个问题:

foreach (var x in configurationDictionary.ToArray())
{
     ....
}

或者,如果您使用的是 LINQ:

var someResult = configurationDictionary.ToArray().Where(...).Select(...)

【讨论】:

  • 我不知道我会接到多少电话,但我很确定这会按顺序来,我被建议在这个上做一个单例,但我不知道这是否是一个好方法。
  • 如果我这样设置属性会怎样:[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)] ??
  • 两个单一的意味着您的服务类的一个实例,并且只有一个线程。这意味着您一次只能服务一个请求。这意味着没有并发问题,但是您的服务无法支持大量客户端(我认为如果请求已经在进行中,则请求会排队)。
  • 所以,长话短说,如果您只有几个客户,那么两个单身都可以满足您的需求。
  • 我不知道是否值得一提,但 ScanRecieved 方法将通过 TCP 连接将字符串发送到已处理的设备打印机,这就是我需要按顺序排列的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
相关资源
最近更新 更多