簡體   English   中英

將兩種不同類型的事件分配給事件處理程序的區別

[英]Difference between two different types of assigning events to event handlers

我在SO中看到了這個示例代碼,它說一個練習很糟糕而另一個很好。 但我不明白為什么? 事實上,我得到了那個着名的RCW COM對象錯誤,該帖子說這可能是一個原因。

public class SomeClass
{
    private Interop.ComObjectWrapper comObject;
    private event ComEventHandler comEventHandler;

    public SomeClass()
    {
        comObject = new Interop.ComObjectWrapper();

        // NO - BAD!
        comObject.SomeEvent += new ComEventHandler(EventCallback);

        // YES - GOOD!
        comEventHandler = new ComEventHandler(EventCallback);
        comObject.SomeEvent += comEventHandler
    }

    public void EventCallback()
    {
        // DO WORK
    }

}

編輯:這是源的鏈接: 不能使用已與其基礎RCW分離的COM對象

我認為這兩個代碼片段是相同的,我們在這里沒有強/弱引用的任何問題。

背景

首先,如果我們的Interop.ComObjectWrapper提供CLR事件(即在Interop.ComObjectWrapper中存儲事件處理程序的事件),我們肯定會從ComObjectWrapper到我們的對象獲得強引用。

任何代表包含兩個部分: Target類型的object和方法指針以特定的方法。 如果Targetnull ,則回調指向靜態方法。

不可能有一個類型為WeakReference的 Target的委托。 有所謂的弱事件模式,但它實現在EventManager之上而不是普通的委托。

在字段中存儲事件處理程序將無濟於事。 第1部分

內部事件實現意味着在訂閱事件之后:

comObject.SomeEvent += EventCallback;

comObject對象隱含地擁有對SomeClass對象的強引用。 無論您使用何種訂閱技術以及ComObject是否是COM對象包裝器,這都是正確的。

訂閱事件會在生命周期中添加兩個對象之間的隱式依賴關系。 這就是為什么.NET世界中最常見的內存泄漏是由訂閱長期存在的對象的事件引起的。 在應用程序中可訪問事件持有者之前,事件訂閱者不會死

在字段中存儲事件處理程序將無濟於事。 第2部分

但事件如果我的假設不正確並且ComObjectWrapper提供了一些弱事件模式的概念,那么在字段中保存事件處理程序將無濟於事。

讓我們回顧一下event關鍵字的含義:

private event ComEventHandler comEventHandler;
... 
comEventHandler = new ComEventHandler(EventCallback);

在當前字段中保存回調(基本上我們可以將私有事件視為簡單的委托字段)不會更改現有行為。

我們已經知道委托是一個簡單的對象,它存儲對Target對象(即SomeClass對象)和方法(即public void EventCallBack() )的public void EventCallBack() 這意味着在字段中存儲附加委托會從SomeClass本身添加對SomeClass附加引用。

基本上,在字段中存儲事件處理程序在語義上等同於在SomeClass中存儲附加引用:

private SomeClass someClass;

public SomeClaas(){//這與在comEventHandler字段中存儲委托//基本相同someClass = this; }

SomeClass存儲強引用不會延長當前對象的生命周期。 這意味着,如果ComObjectWrapper不會抱持着強烈的參考SomeClass對象存儲事件處理程序在comEventHandler不會延長SomeClass的一生並不會阻止SomeClass收集垃圾。

結論

在私有字段中存儲事件處理程序不會延長對象的生命周期,也不會阻止它進行垃圾回收。

這就是為什么以下代碼片段在對象生存期方面沒有區別:

    // GOOD!
    comObject.SomeEvent += new ComEventHandler(EventCallback);

    // EVEN BETTER!
    comObject.SomeEvent += EventCallback;

    // NOT GOOD, BECAUSE WAN'T HELP!
    comEventHandler = new ComEventHandler(EventCallback);
    comObject.SomeEvent += comEventHandler

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM