To avoid losing an event hook-up from a COM source it is necessary to hold a local reference to the source of the event to avoid unwanted garbage collection. This is a concern for VSTA hosts hooking into DTE events as well as VSTA add-ins which use a direct reference to a COM host instead of a proxy.
For example, in the SDK the DTE source events are each saved in a local variable and hooked into from these variables. If you attempt to hook into the events without saving event sources the hook-ups can be lost.
To test if an event hookup will preset, call GC.Collect in the event sink and re-fire. If the event is hit again the hookup should persist.
Example of how to hook into DTE events from a host:
When events sources are saved, event hookups will continue to work after garbage collection.
private EnvDTE.BuildEvents buildEvents;
private void HookupDteEvents_GOOD()
{
// Save a copy of the event sync locations so they don't get
// garbage collected.
this.buildEvents = this.dte.Events.BuildEvents;
this.buildEvents.OnBuildBegin += new
EnvDTE._dispBuildEvents_OnBuildBeginEventHandler(buildEvents_OnBuildBegin);
}
void buildEvents_OnBuildBegin(EnvDTE.vsBuildScope Scope,
EnvDTE.vsBuildAction Action)
{
//Call GC.Collect to test if the event hookup will persist
System.Windows.Forms.MessageBox.Show(
"Call GC.Collect after firing event to test hook-up");
GC.Collect();
}
Example of how NOT to hook into DTE events from a host:
When events sources are not saved, event hookups will not continue to work after garbage collection.
private void HookupDteEvents_BAD()
{
// DON’T DO THIS
// Hook into the event through the dte w/o saving source
this.dte.Events.BuildEvents.OnBuildBegin +=new
EnvDTE._dispBuildEvents_OnBuildBeginEventHandler(buildEvents_OnBuildBegin);
}
void buildEvents_OnBuildBegin(EnvDTE.vsBuildScope Scope,
EnvDTE.vsBuildAction Action)
{
//Call GC.Collect to test if the event hookup will persist
System.Windows.Forms.MessageBox.Show(
"Call GC.Collect after firing event to test hook-up");
GC.Collect();
}
Example of how to hook into host events from an add-in using a direct reference to a COM host:
When events sources are saved, event hookups will continue to work after garbage collection. From MyAppVB6 sample.
private void AppAddIn_Startup(object sender, EventArgs e)
{
this.Document.KeyPress += new
__Document_KeyPressEventHandler(Document_KeyPress);
doc = this.Document;
doc.KeyPress += new
__Document_KeyPressEventHandler(doc_KeyPress);
//if the local variable is saved, hooking into this.Document will work
//this.Document.KeyPress += new
// __Document_KeyPressEventHandler(Document_KeyPress);
}
Document doc;
void doc_KeyPress(ref short KeyCode)
{
System.Windows.Forms.MessageBox.Show(
"Hooking into this.Document with saving it won't work");
GC.Collect();
}
Example of how NOT to hook into host events from an add-in using a direct reference to a COM host:
When events sources are not saved, event hookups will not continue to work after garbage collection. From MyAppVB6 sample.
private void AppAddIn_Startup(object sender, EventArgs e)
{
this.Document.KeyPress += new
__Document_KeyPressEventHandler(Document_KeyPress);
}
void Document_KeyPress(ref short KeyCode)
{
System.Windows.Forms.MessageBox.Show(
"Hooking into this.Document w/o saving it won't work");
GC.Collect();
}
Posted
Apr 29 2009, 11:00 AM
by
Melody