C# 多线程WCF服务中的高效集合维护

C# 多线程WCF服务中的高效集合维护,c#,multithreading,wcf,synchronization,C#,Multithreading,Wcf,Synchronization,我们有一个简单的WCF服务,标记为InstanceContextMode=Single和ConcurrencyMode=Multiple。对于返回列表的方法,我们只返回列表的本地副本,而不是在调用时返回数据库并填充列表。该列表由一个后台线程维护,该线程每24小时进入我们的数据库并重新填充该列表。我们通过在两个位置锁定对象来处理并发性问题:返回集合的方法内部和填充集合的方法内部 我的问题是,我们如何才能使这更有效。目前,我们有一个瓶颈in-out服务方法“GetCustomers”,客户端将调用该

我们有一个简单的WCF服务,标记为InstanceContextMode=Single和ConcurrencyMode=Multiple。对于返回列表的方法,我们只返回列表的本地副本,而不是在调用时返回数据库并填充列表。该列表由一个后台线程维护,该线程每24小时进入我们的数据库并重新填充该列表。我们通过在两个位置锁定对象来处理并发性问题:返回集合的方法内部和填充集合的方法内部

我的问题是,我们如何才能使这更有效。目前,我们有一个瓶颈in-out服务方法“GetCustomers”,客户端将调用该方法:

public List<ZGpCustomer> GetCustomers()
{
    List<ZGpCustomer> customerListCopy = new List<ZGpCustomer>();
    lock (_customerLock)
    {
        customerListCopy = new List<ZGpCustomer>(_customers);
    }

    return customerListCopy;
}
public List GetCustomers()
{
List customerListCopy=新列表();
锁定(_customerLock)
{
customerListCopy=新列表(\u客户);
}
返回客户列表;
}
由于“_customers”仅每24小时填充一次,因此似乎只有在修改集合时才需要锁定GetCustomers方法。按照目前的设置方式,如果1000个请求同时进入,我们将有效地对1000个请求进行排队,因为一次只有一个线程可以访问该方法。这使得服务的多线程方面有些无用,不是吗


这种模式有最佳实践吗?我应该使用更合适的数据收集来存储我的对象吗?“BlockingCollection”更合适吗?

肯定有更有效的方法。诀窍是保持对集合的主引用不变。这样,您就不必在读卡器端同步访问。只有写东西的人需要一把锁。读者方不需要任何东西,这意味着读者保持高度并发。您唯一需要做的就是将
\u customers
引用标记为volatile

// Variable declaration
object lockobj = new object();
volatile List<ZGpCustomer> _customers = new List<ZGpCustomer>();

// Writer
lock (lockobj)
{
  // Create a temporary copy.
  var copy = new List<ZGpCustomer>(_customers);

  // Modify the copy here.
  copy.Add(whatever);
  copy.Remove(whatever);

  // Now swap out the references.
  _customers = copy;
}

// Reader
public List<ZGpCustomer> GetCustomers()
{
    return new List<ZGpCustomer>(_customers);
}

在没有任何证据的情况下:您可以查看System.collections.Concurrent中的集合,我想这会比锁处理得更快:谢谢您的回复……您能再解释一下关于返回客户列表只读副本的第二条评论吗?如果不遵循您关于只读拷贝的建议,我会有什么风险?我应该说是wrapper,而不是copy,以说明在
GetCustomers
中可能不需要实际的拷贝操作,这将进一步提高性能。啊,好的,明白了。再次感谢你提供的信息。我从来没有仔细研究过volatile的价值,所以我想是时候了!请注意……
volatile
是一个棘手的关键词:)我在这里介绍的技巧绝对是一个高级技巧。我不确定是否应该将此作为单独的问题提交,但它仍然与您上面的答案相关。我把我的开发代码换成了你的建议,当我用一堆请求点击服务时,我真的没有看到响应时间的增加。我从一个控制台应用程序向GetCustomers并行发送了40个电话,它们都会立即发送,但响应速度似乎与我进行更改之前相同。该服务托管在IIS中,因此我不确定这是需要更改的IIS设置还是需要更改的服务配置。
// Reader
public IList<ZGpCustomer> GetCustomers()
{
    return _customers.AsReadOnly();
}