outlook - Outlook VSTO AddIn 如何避免 RaceOnRCWCleanup
问题描述
我要实现的目标是使用 Inspector 上的 AppProperty Change 事件正确处理日历上的拖放事件:
每当用户与界面交互(Explorer.SelectionChange、NewInspector、CloseInspector 等)时,我都会更新 currentAppointmentItem。每当用户与界面交互(SelectionChange、NewInspector、CloseInspector)时,我都会更新 currentInspector 更新意味着我尝试设置/取消设置相应的事件处理程序和 Marshal.ReleaseComObject。最后将引用归零。
但是,当用户只是单击日历中的 AppointmentItem 时,不会创建 Inspector 窗口。因此我无法捕捉 AppPropertyChange 事件。所以我决定在选定的 AppointmentItem 上调用 GetInspector,以防它不为空。我尝试使用它来接收 AppProperty 事件的更改,以便我可以正确处理日历上的拖放事件
问题:从 Microsoft 文档中,我了解到,每当您丢失对 currentAppointmentItem 的引用时,您还应该使用 Marshal.ReleaseComObject ,否则您会冒其他问题的风险。现在我遇到了我无法捕捉到的异常:RaceOnRCWCleanup ...似乎我试图释放一个仍在使用的 COM 对象(可能由 Outlook 使用)。我怎样才能避免这种情况?Marshal.ReleaseComObject(currentAppointmentItem) 是否正确
我注册了 Outlook.Explorer 上的 SelectionChange 事件。在那里,我尝试使用以下方式注册 currentAppointment:
[...]
log.Info("Selection_Change");
if (currentExplorer == null)
{
return;
}
try
{
log.Info("Selection_Change: " + currentExplorer.Caption);
Outlook.MAPIFolder selectedFolder = currentExplorer.CurrentFolder;
if (currentExplorer.Selection.Count > 0)
{
Object selObject = currentExplorer.Selection[1];
if (selObject is Outlook.AppointmentItem)
{
currentAppointmentItem = (Outlook.AppointmentItem)selObject;
Inspectors_NewInspector(currentAppointmentItem.GetInspector);
}
[...]
请注意:INspectors_NewInspector 也会在 Inspectors 集合中调用。
NewInspector 的代码就像
void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
try
{
log.Info("Inspectors_NewInspector");
// This function (apparently) gets kicked off whenever a user opens a new or existing item
// in Outlook (Calendar appointment, Email, etc).
// We can intercept it, modify it's properties, before letting our Ribbon know about its existance.
//
if (Inspector != null)
{
log.Info("Inspectors_NewInspector: " + Inspector.Caption);
unregisterCurrentInspector();
currentInspector = Inspector;
object item = Inspector.CurrentItem;
if (item == null)
return;
if (!(item is Outlook.AppointmentItem))
return;
unregisterCurrentAppointmentItem();
currentAppointmentItem = (Outlook.AppointmentItem)item;
currentAppointmentItem.PropertyChange += AppPropertyChanged; // Handle situations where the
// user tries to convert an appointment w/ an agreedo protocol to a recurring appointment.
// This needs to be avoided .
currentAppointmentItem.CustomPropertyChange += AppPropertyChanged;
}
((Microsoft.Office.Interop.Outlook.InspectorEvents_10_Event)Inspector).Close += Inspector_Close;
} catch (Exception ex)
{
log.Error(ex.Message);
}
}
unregisterCurrentApppointmentItem :
private void unregisterCurrentAppointmentItem()
{
try
{
log.Info("unregisterCurrentAppointmentItem");
if (currentAppointmentItem != null)
{
currentAppointmentItem.PropertyChange -= AppPropertyChanged; // Handle situations where the
currentAppointmentItem.CustomPropertyChange -= AppPropertyChanged;
Marshal.ReleaseComObject(currentAppointmentItem);
currentAppointmentItem = null;
}
} catch (Exception ex)
{
log.Error(ex.Message);
}
}
unregisterCurrentInspector:
private void unregisterCurrentInspector()
{
log.Info("unregisterCurrentInspector");
if (currentInspector != null)
{
((Microsoft.Office.Interop.Outlook.InspectorEvents_10_Event)currentInspector).Close -= Inspector_Close;
Marshal.ReleaseComObject(currentInspector);
currentInspector = null;
}
}
对此有何建议?
我已经尝试/考虑的内容:
解决方案
首先,不需要模拟NewInspector
事件。相反,您需要正确设置事件处理程序。看来您只需要实现检查器或资源管理器包装器。有关详细信息,请参阅为检查器实现包装器并在每个检查器中跟踪项目级事件。
似乎我试图释放一个仍在使用的 COM 对象(可能由 Outlook 使用)。我怎样才能避免这种情况?Marshal.ReleaseComObject(currentAppointmentItem) 是否正确
是的。但是你真的应该对通过调用属性和方法在你的代码中检索到的对象使用这个方法。您不应该释放由 Office 应用程序作为参数传递的对象。查看何时在 .NET 中开发的 Office 加载项中发布 COM 对象一文,该文章解释了可能存在的缺陷并回答了最广泛传播的问题。
推荐阅读
- javascript - 异步函数不在等待时等待
- python - Python(17874,0x111e92dc0)malloc:无法分配区域
- neo4j - 三重存储或图形数据库更适合这个应用程序?
- autodesk-forge - 为什么 Autodesk Forge 的“workflowAttribute”没有出现在模型衍生工作的 webhook 更新中?
- java - 如何找到这个递归函数的递归关系?
- python - IBM Power9 ppc64le 上的 Tensorflow - 可以删除 libtensorflow.so 吗?
- google-api - Google Drive 评论 API 在没有评论时显示未解决的评论
- python - Solve_ivp 输出,进入轨道图?
- ruby - Ruby 强参数:Integer 的 NoMethodError 未定义方法允许
- python-3.x - 使用 BeautifulSoup 进行网页抓取