2011-09-26 70 views
0

我的ASP.Net C#Web应用程序允许其用户使用FTP将来自我服务器上帐户的文件发送到任何远程服务器。我已经实现了一个WCF服务来做到这一点。该服务为每个产生工作线程的用户实例化一个类,该工作线程在服务器上执行FTP操作。客户端向服务发送命令,服务找到分配给客户端的工作线程并启动FTP命令。然后,客户端每两秒轮询一次服务以获取FTP操作的状态。当客户端发送“disconnect”命令时,类和执行FTP操作的工作线程被销毁。我的WCF服务可以使用单例可缩放吗?

FTP工作线程需要在客户端的查询之间保留,因为FTP处理可能需要很长时间。所以,我需要一种方法让客户始终在对服务的调用之间获得相同的FTP类实例。我实现了这个服务作为一个单身,这样的:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
public class UserFtpService : IUserFtpService 
{ 
    private SortedDictionary<string, UserFTPConnection> _clients = new SortedDictionary<string, UserFTPConnection>(); 

    ... 
} 

其中“UserFTPConnection”是包含工作线程和用户的帐户名是用于字典中的索引类。

我有这样的问题:在我读过关于WCF的书中,单例实例被称为“可伸缩性的敌人”。我明白为什么这样。有没有更好的方法来确保客户端获得UserFTPConnection的查询之间的WCF服务,而不是使用单例的同一个实例?

回答

2

其实这里你的第一个问题是同步访问这个静态对象。 Dictionary<TKey, TValue>不是线程安全的,因此您必须确保只有一个线程同时访问它。因此,您应该在lock中包含对此词典的所有访问权限,当然假设您有写作方法和其他正在阅读的方法。如果你只是在阅读,你不需要同步。至于单身人士是可扩展性的敌人,这实在是一个夸张的陈述,没有特定的场景就毫无意义。这实际上取决于确切的场景和实施。在你的例子中,你只显示了一个字典=>所以我们可以说的是,你需要确保没有线程正在从这个字典中读取,而另一个线程正在写入,并且在其他线程正在读取时没有线程正在写入这个字典。

例如在.NET 4.0中,您可以使用ConcurrentDictionary<TKey, TValue>类,在这种情况下线程安全。

但有一件事是肯定的:虽然单身模式可能会或可能不是可扩展性的敌人,具体取决于具体实现,但单身模式是孤立单元可测试性的主要敌人。

+0

我没有显示代码的其余部分,因为这与我的问题无关,但对字典的访问位于“锁定”块内,因此可以正确同步。当我开始查找条目时,我的印象是“SortedDictionary”速度更快,这比插入或删除条目的速度更重要。我不知道C#中的任何排序的并发字典。 – Escovado

+0

@Escovado,*排序字典*?从来没有听说过这样的事情。字典是散列表,用于执行密钥查找的设计,没有为这些数据结构定义每个命令或排序的概念。 –

+0

是的,SortedDictionary在这里:http://msdn.microsoft.com/en-us/library/f7fta44c.aspx – Escovado

1

如果你打算使用单身人士,我建议还设置ConcurrencyMode ConcurrencyMode.Multiple。例如...

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)] 
public class UserFtpService : IUserFtpService 
{ 
} 

如果你不这样做,你的WCF服务将是一个单身,但只允许一个线程在同一时间,这肯定会影响性能访问。当然,你需要确保集合的线程安全性(如前面提到的答案)。

+0

谢谢你的提示。一次一个线程是不可接受的。我是这些服务的新手。 – Escovado

+0

顺便说一句 - 你知道一个不同的(或更好的方法)来确保客户端获得我的UserFTPConnection类的相同实例,该请求在服务器请求之间持续存在吗? – Escovado

相关问题