Il presente articolo è stato tradotto automaticamente. Passare il puntatore sulle frasi nell'articolo per visualizzare il testo originale. Ulteriori informazioni.
Traduzione
Originale
Questo argomento non è stato ancora valutato - Valuta questo argomento

Modelli di eventi deboli

Nelle applicazioni, è possibile che i gestori associati a origini evento non vengano eliminati insieme all'oggetto listener che ha associato il gestore all'origine. Tale situazione può causare perdite di memoria. Windows Presentation Foundation (WPF) introduce un modello di progettazione che può essere utilizzato per risolvere questo problema, fornendo una classe di gestione dedicata per eventi particolari e implementando un'interfaccia nei listener relativi all'evento in questione. Questo modello di progettazione è noto come modello di evento debole.

L'utilizzo di listener di eventi può causare perdite di memoria. La tecnica standard di ascolto di un evento consiste nell'utilizzare la sintassi specifica del linguaggio che associa un gestore a un evento in un'origine. In C#, ad esempio, la sintassi è la seguente: source.SomeEvent += new SomeEventHandler(MyEventHandler).

Questa tecnica crea un riferimento forte dall'origine evento al listener di eventi. Di norma, l'associazione di un gestore eventi per un listener fa sì che la durata dell'oggetto del listener sia influenzata dalla durata dell'oggetto dell'origine, a meno che il gestore eventi non venga rimosso in modo esplicito. In determinate circostanze, tuttavia, è possibile che la durata dell'oggetto del listener sia controllata da altri fattori, ad esempio l'eventuale appartenenza del listener alla struttura ad albero visuale dell'applicazione, non dalla durata dell'origine. Se la durata dell'origine va oltre la durata del listener, il modello di eventi standard causa una perdita di memoria: il listener viene tenuto vivo più a lungo di quanto previsto.

Il modello di evento debole è progettato per risolvere questo problema di perdita di memoria e può essere utilizzato ogni qualvolta un listener deve effettuare la registrazione per un evento ma non conosce in modo esplicito il momento in cui annullare la registrazione. Il modello di evento debole può inoltre essere utilizzato ogni qualvolta la durata dell'oggetto dell'origine supera la durata dell'oggetto utile del listener. In questo caso, utile è determinato dall'utente. Il modello di evento debole consente al listener di registrarsi per l'evento e riceverlo senza influire in alcun modo sulle caratteristiche di durata dell'oggetto del listener. Di fatto, il riferimento implicito dall'origine non determina l'eventuale idoneità del listener per Garbage Collection. Si tratta di un riferimento debole, da cui la denominazione del modello di evento debole e delle API correlate. Il listener può essere sottoposto a Garbage Collection o altrimenti eliminato e l'origine può continuare senza mantenere riferimenti del gestore non sottoponibili a Garbage Collection relativi a un oggetto ora eliminato.

L'implementazione del modello di evento debole sarà interessante soprattutto per gli autori dei controlli, responsabili in larga parte del comportamento e del contenimento del controllo oltre che dell'impatto che questo ha sulle applicazioni nelle quali viene inserito. Ciò include il comportamento relativo alla durata dell'oggetto del controllo, in particolare la gestione del problema di perdita di memoria descritto.

Determinati scenari si prestano implicitamente all'applicazione del modello di evento debole. Uno di questi è l'associazione dati. Nell'associazione dati accade comunemente che l'oggetto di origine sia completamente indipendente dall'oggetto listener, che è una destinazione di un'associazione. Il modello di evento debole viene già applicato a molti aspetti dell'associazione dati WPF rispetto al modo in cui vengono implementati gli eventi.

Esistono tre modi per implementare il modello di evento debole. Nella tabella seguente sono elencati i tre approcci e fornisce alcune linee guida per l'utilizzo di.

Approccio

quando implementare

Utilizzare una classe debole esistente del gestore degli eventi

Se l'evento che si desidera sottoscrivere ha una corrispondenza WeakEventManager, utilizzare il gestore di evento debole esistente. Per un elenco di gestori degli eventi deboli inclusi in WPF, vedere la gerarchia di ereditarietà in WeakEventManager classe. Si noti, tuttavia, che sono relativamente pochi gestori degli eventi deboli inclusi in WPF, pertanto sarà probabilmente necessario selezionare uno degli altri approcci.

Utilizzare una classe debole generica del gestore degli eventi

Utilizzare un oggetto generico WeakEventManager<TEventSource, TEventArgs> quando un oggetto esistente WeakEventManager non è disponibile, si desidera che un modo semplice per implementare e non quanto riguarda efficienza. L'oggetto generico WeakEventManager<TEventSource, TEventArgs> è meno efficiente di esistente o un gestore di evento debole personalizzato. Ad esempio, la classe generica consente più reflection per individuare l'evento specificato il nome dell'evento. Inoltre, il codice per registrare l'evento utilizzando l'oggetto generico WeakEventManager<TEventSource, TEventArgs> è più dettagliato di utilizzo di un oggetto esistente o di un oggetto personalizzato WeakEventManager.

Creare una classe debole personalizzata del gestore degli eventi

Creare un oggetto personalizzato WeakEventManager quando si esistente WeakEventManager non è disponibile e si desidera che il migliore efficienza. Utilizzando un oggetto personalizzato WeakEventManager per sottoscrivere un evento sarà più efficiente, ma si incorre il costo di scrittura del codice nella parte superiore.

Nelle sezioni seguenti viene descritto come implementare il modello di evento debole. Ai fini di questa discussione, l'evento da sottoscrivere presenta le caratteristiche descritte di seguito.

  • il nome di evento è SomeEvent.

  • L'evento viene generato da EventSource classe.

  • Il gestore eventi il tipo: SomeEventEventHandler o EventHandler<SomeEventEventArgs>).

  • l'evento passa un parametro di tipo SomeEventEventArgs i gestori eventi.

Aa970850.collapse_all(it-it,VS.110).gifUtilizzando una classe debole esistente del gestore degli eventi

  1. Trovare un gestore di evento debole esistente.

    Per un elenco di gestori degli eventi deboli inclusi in WPF, vedere la gerarchia di ereditarietà in WeakEventManager classe.

  2. Utilizzare il nuovo gestore di evento debole anziché collegamento normale dell'evento.

    Ad esempio, se il codice utilizza il modello seguente per sottoscrivere un evento:

    source.SomeEvent += new SomeEventEventHandler(OnSomeEvent);
    

    Modificare il seguente modello:

    SomeEventWeakEventManager.AddHandler(source, OnSomeEvent);
    

    Analogamente, se il codice utilizza il modello seguente per annullare la sottoscrizione a un evento:

    source.SomeEvent -= new SomeEventEventHandler(OnSome);
    

    Modificare il seguente modello:

    SomeEventWeakEventManager.RemoveHandler(source, OnSomeEvent);
    

Aa970850.collapse_all(it-it,VS.110).gifUtilizzando la classe debole generica del gestore degli eventi

  1. Utilizzare l'oggetto generico WeakEventManager<TEventSource, TEventArgs> classe anziché collegamento normale dell'evento.

    Quando si utilizzano WeakEventManager<TEventSource, TEventArgs> per registrare listener di eventi, fornire origine eventi e EventArgs tipo come parametri di tipo alla classe e alla chiamata AddHandler come illustrato nel codice seguente:

    WeakEventManager<EventSource, SomeEventEventArgs>.AddHandler(source, "SomeEvent", source_SomeEvent);
    

Aa970850.collapse_all(it-it,VS.110).gifCreare una classe debole personalizzata del gestore degli eventi

  1. Copiare il seguente modello di classe al progetto.

    Questa classe eredita dalla classe WeakEventManager.

    
    class SomeEventWeakEventManager : WeakEventManager
    {
    
        private SomeEventWeakEventManager()
        {
    
        }
    
        /// <summary>
        /// Add a handler for the given source's event.
        /// </summary>
        public static void AddHandler(EventSource source, 
                                      EventHandler<SomeEventEventArgs> handler)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (handler == null)
                throw new ArgumentNullException("handler");
    
            CurrentManager.ProtectedAddHandler(source, handler);
        }
    
        /// <summary>
        /// Remove a handler for the given source's event.
        /// </summary>
        public static void RemoveHandler(EventSource source, 
                                         EventHandler<SomeEventEventArgs> handler)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (handler == null)
                throw new ArgumentNullException("handler");
    
            CurrentManager.ProtectedRemoveHandler(source, handler);
        }
    
        /// <summary>
        /// Get the event manager for the current thread.
        /// </summary>
        private static SomeEventWeakEventManager CurrentManager
        {
            get
            {
                Type managerType = typeof(SomeEventWeakEventManager);
                SomeEventWeakEventManager manager = 
                    (SomeEventWeakEventManager)GetCurrentManager(managerType);
    
                // at first use, create and register a new manager
                if (manager == null)
                {
                    manager = new SomeEventWeakEventManager();
                    SetCurrentManager(managerType, manager);
                }
    
                return manager;
            }
        }
    
    
    
        /// <summary>
        /// Return a new list to hold listeners to the event.
        /// </summary>
        protected override ListenerList NewListenerList()
        {
            return new ListenerList<SomeEventEventArgs>();
        }
    
    
        /// <summary>
        /// Listen to the given source for the event.
        /// </summary>
        protected override void StartListening(object source)
        {
            EventSource typedSource = (EventSource)source;
            typedSource.SomeEvent += new EventHandler<SomeEventEventArgs>(OnSomeEvent);
        }
    
        /// <summary>
        /// Stop listening to the given source for the event.
        /// </summary>
        protected override void StopListening(object source)
        {
            EventSource typedSource = (EventSource)source;
            typedSource.SomeEvent -= new EventHandler<SomeEventEventArgs>(OnSomeEvent);
        }
    
        /// <summary>
        /// Event handler for the SomeEvent event.
        /// </summary>
        void OnSomeEvent(object sender, SomeEventEventArgs e)
        {
            DeliverEvent(sender, e);
        }
    }
    
    
    
  2. Sostituire SomeEventWeakEventManager nome con un nome.

  3. Sostituire i tre nomi descritti in precedenza con i nomi corrispondenti per l'evento. (SomeEvent, EventSourcee SomeEventEventArgs)

  4. Per impostare la visibilità (pubblica/interna/privata) della classe debole del gestore degli eventi alla stessa visibilità di gestisce l'evento.

  5. Utilizzare il nuovo gestore di evento debole anziché collegamento normale dell'evento.

    Ad esempio, se il codice utilizza il modello seguente per sottoscrivere un evento:

    source.SomeEvent += new SomeEventEventHandler(OnSomeEvent);
    

    Modificare il seguente modello:

    SomeEventWeakEventManager.AddHandler(source, OnSomeEvent);
    

    Analogamente, se il codice utilizza il modello seguente per annullare la sottoscrizione a un evento:

    source.SomeEvent -= new SomeEventEventHandler(OnSome);
    

    Modificare il seguente modello:

    SomeEventWeakEventManager.RemoveHandler(source, OnSomeEvent);
    
Il documento è risultato utile?
(1500 caratteri rimanenti)

Aggiunte alla community

AGGIUNGI
© 2013 Microsoft. Tutti i diritti riservati.