簡體   English   中英

如何將委托作為參數傳遞給訂閱作為事件處理程序?

[英]How to pass a delegate as an argument to subscribe as an event handler?

我有一個提供事件StkQuit的外部應用程序。

我在靜態類中訂閱此事件,該類處理我的應用程序和[外部]應用程序之間的所有通信。 我想使用另一個位於我的表單類的處理程序訂閱StkQuit事件。

此處理程序將通知用戶外部應用程序已關閉。 我想在名為SubscribeToStkQuit的靜態類中有一個泛型方法,它接受委托作為參數,並將該委托(指我的表單類中的處理程序) StkQuitStkQuit事件。

這可能嗎? 這是實現此類功能的最優雅/最簡單的方法嗎?

我的示例代碼:

表格類

public delegate void dForceClose();
public void SubscribeToStkQuit(dForceClose forceClose)
{
    UtilStk.SubscribeToStkQuit(forceClose = new dForceClose(ForceClose));
}
private void ForceClose()
{
    MessageBox.Show("TEST");
}

靜態類

private static AgUiApplication _stkUiApplication;
public static void SubscribeToStkQuit(Delegate subscribeHandler)
{
    _stkUiApplication.OnQuit += subscribeHandler;          
}

[更新]

根據評論,我已更新代碼,如下所示:

public delegate void dForceClose(object sender, EventArgs e);
public void SubscribeToStkQuit(dForceClose forceClose)
{
    UtilStk.SubscribeToStkQuit(forceClose = new dForceClose(ForceClose));
}
private void ForceClose(object sender, Eventargs e)
{
    MessageBox.Show("TEST");
}

我仍然得到演員異常。 有任何想法嗎 ??

[更新#2]

我仍然遇到這個問題。 在我的靜態類中,當OnQuit觸發時,我已經有了一個處理程序:

private static AgUiApplication _stkUiApplication;
public static bool CheckThatStkIsAvailable()
{
    object stkApplication = null;
    try
    {
        stkApplication = Marshal.GetActiveObject(_stkProgId);
        _stkUiApplication = stkApplication as AgUiApplication;
        _stkUiApplication.OnQuit += StkQuit;
        return true;
    }
    catch (Exception)
    {
        // handle this
    }
}

private static void StkQuit()
{
    _stkUiApplication.OnQuit -= StkQuit;
    Marshal.FinalReleaseComObject(_stkUiApplication);
    Marshal.FinalReleaseComObject(_stkRoot);
}

這很好用。 所以我想我會為_stkUiApplication創建一個公共屬性,並以相同的方式從表單類訂閱:

靜態類

public static AgUiApplication StkUiApplication
{
    get { return _stkUiApplication; }
}

表格類

private void SubscribeToStkQuit()
{
    UtilStk.StkUiApplication.OnQuit += StkQuit;
}

private void StkQuit()
{
    MessageBox("TEST");
}

如果使用實例方法訂閱靜態事件,則在處理靜態事件之前不會對實例進行垃圾回收(除非您取消訂閱)。

這將導致內存泄漏。

除此之外,你的代碼的問題是,簽名ForceClose()不匹配_stkUiApplication.OnQuit它需要ForceClose(object sender, SomeKindOfEventArgs e)

它應該是UtilStk.SubscribeToStkQuit(forceClose => (s, e){ForceClose();});

編輯:

您對外部應用的引用是靜態的:

private static AgUiApplication _stkUiApplication;

所以它會在你的申請期間存在。 添加事件處理程序

 _stkUiApplication.OnQuit

將引用傳遞給表單類實例上的方法。 此引用現在將在您的應用程序的生命周期中保留,因此不能進行垃圾回收。

要處理這種情況,要么在處理偵聽對象時顯式取消注冊( - =)處理程序,要么使用靜態處理程序處理靜態事件。

我錯誤地認為你最初是在描述網絡表單,這會改變一些事情(你可能只會實例化一個Form ),但無論如何都是如此。 這是一個很好的做法。

要解決當前問題:您需要輸入傳遞給的參數:

public static void SubscribeToStkQuit(Delegate subscribeHandler)
{
    _stkUiApplication.OnQuit += subscribeHandler;          
}

_stkUiApplication.OnQuit的類型

就像是

public static void SubscribeToStkQuit(EventHandler<EventArgs> subscribeHandler)
{
    _stkUiApplication.OnQuit += subscribeHandler;          
}

然后你可以這樣做:

public void SubscribeToStkQuit()
{
    UtilStk.SubscribeToStkQuit((sender, args) => ForceClose(sender, args));
}

是的你可以!

但最好使用動作和函數,這些參數化在參數化方面都很靈活(所有這些都在System命名空間中)。

無論如何,我還有另一個建議:你為什么不使用事件訪問器? 您可以在靜態類中創建一個:

public event EventHandler Quit { add { _stkUiApplication.OnQuit += value; } remove { _stkUiApplication.OnQuit -= value; } }

關於操作和函數,這些也是委托,因此您可以將它們作為任何委托的輸入參數隨處使用。

也許您可以使用事件訪問器並以.NET方式執行,不是嗎?

暫無
暫無

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

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