我有一个提供事件StkQuit的外部应用程序。
我在一个静态类中订阅此事件,它处理应用程序和外部应用程序之间的所有通信。我希望使用位于窗体类上的另一个处理程序订阅StkQuit事件。
此处理程序将通知用户外部应用程序已关闭。我希望静态类中有一个名为SubscribeToStkQuit的泛型方法,它接受委托作为参数,并订阅该委托(引用我的表单类上的处理程序)到StkQuit事件。
这个是可能的吗?这是实现这种功能的最优雅/最简单的方法吗?
我的示例代码:
表单类
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创建一个公共属性,并以同样的方式从form类订阅:
静态类
public static AgUiApplication StkUiApplication
{
get { return _stkUiApplication; }
}表单类
private void SubscribeToStkQuit()
{
UtilStk.StkUiApplication.OnQuit += StkQuit;
}
private void StkQuit()
{
MessageBox("TEST");
}发布于 2011-01-27 13:35:51
如果使用实例方法订阅静态事件,则在释放静态事件之前将不会对实例进行垃圾收集(除非取消订阅)。
这会导致内存泄漏。
除此之外,您的代码的问题是ForceClose()的签名与_stkUiApplication.OnQuit不匹配--它需要是ForceClose(object sender, SomeKindOfEventArgs e)。
应该是UtilStk.SubscribeToStkQuit(forceClose => (s, e){ForceClose();});
编辑:
对外部应用程序的引用是静态的:
private static AgUiApplication _stkUiApplication;因此,它将在您的应用程序的持续时间内存活。将事件处理程序添加到
_stkUiApplication.OnQuit在窗体类的实例上传递对方法的引用。这个引用现在将保存在应用程序的生命周期中,因此它不能被垃圾收集。
要处理这种情况,可以在释放侦听对象时显式地取消注册(-=)处理程序,或者使用静态处理程序处理静态事件。
我错误地认为您最初描述的是web表单,这会稍微改变一些事情(您可能只会实例化一个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));
}发布于 2011-01-27 13:38:20
可以,停那儿吧!
但是最好使用动作和函数,它们在参数化方面是灵活的(它们都在系统名称空间中)。
无论如何,我还有一个建议:为什么不使用事件访问器呢?您可以在静态类中创建一个:
public event EventHandler Quit { add { _stkUiApplication.OnQuit += value; } remove { _stkUiApplication.OnQuit -= value; } }关于操作和函数,这些也是委托,因此您可以在任何地方使用它们作为任何委托的输入参数。
也许您可以使用事件访问器并以.NET的方式进行操作,不是吗?
https://stackoverflow.com/questions/4816892
复制相似问题