我正在使用Outlook Addin,我必须处理大量的项目。这需要花费很多时间,因此我尝试在不同的线程中运行处理(使用Task.Factory.StartNew)。但是,这会导致Outlook随机崩溃。
我正在使用Redemption来处理MAPITable,以减少工作量并仅加载相关数据。
目前,唯一对我有用的是在主线程上运行我的所有逻辑(在按钮点击事件中),然而这会长时间锁定Outlook的用户界面,这是用户的观点所不能接受的。图。
是否有人指出如何使用Outlook Addin中的后台线程?
答案 0 :(得分:3)
在我的项目中有类似的代码,我建议如下:
使用Thread类创建新线程,并将其设置为STA。
使用“session.Logon(”profileName“,NoMail:true,NewSession:false)登录会话;”而不是使用MAPIOBJECT。我发现它比使用MAPIOBJECT有更好的性能,我的猜测是它仍然会在主线程上创建MAPIOBJECT时将一些调用回调到主线程。
完成后,在您使用的每个COM对象上使用“Marshal.ReleaseComObject”。这可能是导致不稳定的原因,因为当它的对象太长时,Outlook真的不喜欢。例如,这行代码“var table = rdoFolder.Items.MAPITable;”创建两个COM对象:RDOItems和MAPITable,必须释放它们,因此您需要拆分此行以保存对RDOItems对象的引用。
调用GC.Collect和Application.DoEvents因为如果你没有在所有COM对象上调用Marshal.ReleaseComObject,终结器将尝试释放它们并将挂起,因为COM对象是在线程上创建的不抽取消息循环,它的终结器方法必须在创建它们的线程上运行。
如果可以,请启动辅助进程并在单独的进程中执行此循环。这将使用户界面和后台工作之间达到最大程度的分离。
答案 1 :(得分:1)
在辅助线程中使用RDO对象有什么问题?只要在辅助线程上创建RDOSession,就应该正确初始化MAPI。
另外,TaskFactory使用一个线程池,你最好使用一个显式的Thread类,至少要确保不在不同的线程之间共享RDOSession - 必须在每个线程上初始化MAPI。