【问题标题】:Using Singleton vs Single Call in .NET Remoting?在 .NET 远程处理中使用单例与单调用?
【发布时间】:2009-09-16 18:58:05
【问题描述】:

到目前为止,我编写或使用的所有 .NET 远程处理代码都公开为 SingleCall。

我遇到了一个托管在 Windows 服务中的 .NET 远程处理组件,该服务公开为单例。

此对象有可能被多个客户端同时调用,并且它没有锁或其他措施来保护其内部状态。

如果我对 Singleton 的理解正确,那么这可能会出现大问题,对吗?

【问题讨论】:

  • “没有锁或其他措施来保护其内部状态” ...您确定它是单例吗?据我了解,您需要一个锁才能将(初始)构造限制为单个线程。

标签: .net windows-services singleton remoting


【解决方案1】:

没有比 SingleCall 组件更大的潜力。如果他们试图以不安全的方式访问共享内存位置,两者都会出现问题。

SingleCall 和 Singleton 之间的区别在于,对于 SingleCall ,每个传入请求都将获得一个为处理该调用而创建的已定义类型的新实例。每个实例都有自己的内存空间和实例变量,但它们仍然可以共享静态和全局变量、外部资源、文件、网络连接等。如果 SingleCall 类被编码为以线程不安全的方式访问任何共享内存状态,那么你就会有问题。

另一方面,单例只为所有传入请求创建一个实例,因此根据定义,该单例中使用的每个实例变量实际上在所有传入请求之间共享。一个很好的例子可能是消息发布者,服务器中的所有代码都需要访问它才能向一个或多个订阅的客户端发送消息....

要解决来自@Cocowalla 的评论,请确保如果您这样做,您会覆盖该方法

  MarshalByRefObject.InitializeLifetimeService() 

如图所示,否则你的单例会在一段时间内无人调用时意外消亡......

public class MessageManager : MarshalByRefObject
{
    #region Singleton / MarshalByRefObject code        
    private static MessageManager mgr = 
        new MessageManager(); // creates singleton 
    static MessageManager() { }
    private MessageManager() { }
    public static MessageManager Instance { get { return mgr;  } }
    public override object InitializeLifetimeService() { return (null); }
    #endregion Singlelton code
    // ... other stuff ... 
 }

  // in Remoting Host initialization code...      
   MessageManager mgr = MessageManager.Instance; // generates singleton;
   RemotingServices.Marshal(mgr, URI);

【讨论】:

【解决方案2】:

是的。如果调用者改变了对象的内部状态,而这些方法不是线程安全的,那么你一定会遇到麻烦。该服务器应该是单调用的。

但正如 Charles 所指出的,如果服务器对象访问共享资源(什么有用的服务器不访问?),即使是单调用服务器也会遇到麻烦。不过,这些问题更易于管理。例如,对数据库的访问可以很容易地进行事务处理,因此是安全的。

底线:单次通话是摆脱“一半”麻烦的简单有效方法。坚持下去。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    相关资源
    最近更新 更多