Domanda

Fino a questo punto tutto il codice di remoting .NET con cui ho scritto o lavorato è stato esposto come SingleCall.

Mi sono imbattuto in un componente remoto .NET ospitato in un servizio Windows esposto come Singleton.

Questo oggetto ha il potenziale per essere chiamato da più di un client contemporaneamente e non ha blocchi o altre disposizioni per proteggere il suo stato interno.

Se capisco Singleton correttamente, questo ha il potenziale per grossi problemi corretti?

È stato utile?

Soluzione

Non c'è più potenziale di un componente SingleCall. Entrambi avranno problemi se tentano di accedere a una posizione di memoria condivisa in modo non sicuro.

La differenza tra SingleCall e Singleton è che, per SingleCall, ogni richiesta in arrivo otterrà una nuova istanza del tipo definito creata per gestire quella chiamata. Ogni istanza avrà il proprio spazio di memoria e variabili di istanza, ma potrà comunque condividere variabili statiche e globali, risorse esterne, file, connessioni di rete, ecc. Se la classe SingleCall è codificata per accedere a qualsiasi stato di memoria condivisa in modo thread-safe , allora avrai problemi.

Un Singleton, d'altra parte, ottiene solo un'istanza creata per TUTTE le richieste in arrivo, quindi per definizione, ogni variabile di istanza in uso all'interno di quel singleton è, di fatto, condivisa tra tutte le richieste in arrivo. Un buon esempio potrebbe essere un editore di messaggi, a cui tutto il codice nel server deve accedere per inviare messaggi a uno o più client sottoscritti ....

Per rispondere ai commenti di @Cocowalla, assicurati di fare in modo che tu ignori il metodo

  MarshalByRefObject.InitializeLifetimeService() 

come mostrato, o il tuo singleton si spegnerà inaspettatamente se nessuno lo chiama per un po '...

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);

Altri suggerimenti

Sì. Se i chiamanti modificano lo stato interno dell'oggetto e quei metodi non sono thread-safe, allora sei destinato a metterti nei guai. Quel server dovrebbe essere a chiamata singola.

Ma come sottolinea Charles, se l'oggetto server accede a risorse condivise (e quale server utile no?), anche i server a chiamata singola possono avere problemi. Tuttavia, questi problemi sono più gestibili. L'accesso a un database, ad esempio, può essere facilmente reso transazionale e quindi sicuro.

In conclusione: fare una chiamata singola è un modo semplice ed efficace per sbarazzarsi della metà dei tuoi problemi. Attenersi ad esso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top