Outlook Addin: Work with Threads

I am working on an Outlook Addin and I have to process a large number of items. This takes quite some time, and so I tried to execute processing on another thread (using Task.Factory.StartNew). However, this causes Outlook to crash accidentally.

I use Redemption to work with MAPITable to reduce the load and load only the relevant data.

  • I tried to initialize my RDOSession from both my main thread and my workflow.
  • I tried to get MAPIFolders in the main thread and only work with MAPITable in the workflow.

Currently, the only thing that works for me is to execute all my logic in the main thread (in the button click event), however, this blocks the Outlook user interface for a long period of time, which is unacceptable from the user's point of view.

Does anyone have a pointer on how to work with background threads from an Outlook Addin?

+4
source share
2 answers

Having similar code in my project, I would suggest the following:

  • Create a new thread using the Thread class and set it to STA.

  • Loggin for the session using "session.Logon (" filename ", NoMail: true, NewSession: false); and not using MAPIOBJECT. I found that it has better performance than using MAPIOBJECT, but I think it still marshaled some callbacks to the main thread since MAPIOBJECT was created in the main thread.

  • Use "Marshal.ReleaseComObject" for each COM object that you use as soon as you finish with them. This is probably what causes instability, since Outlook really doesn't like it when the object is too long. For example, this line of code is "var table = rdoFolder.Items.MAPITable;" create two COM objects: RDOItems and MAPITable, both of which must be released, so you need to split this line to save a reference to the RDOItems object.

  • Call GC.Collect and Application.DoEvents , because if you do not name Marshal.ReleaseComObject on the entire COM object, the finalizer will try to release them and it will hang because COM objects were created in a thread that does not pump the message loop, and it The finalizer method must be run on the thread that created them.

  • If you can, do an additional process and run this cycle in a separate process. This will make the maximum separation between the user interface and background work.

+3
source

What is the problem with using RDO objects in a secondary stream? While an RDOSession is created in the secondary stream, the MAPI must be properly initialized.

In addition, TaskFactory uses a thread pool, you would be better off using the explicit Thread class, o at least make sure that the RDOSession is not shared between different threads - the MAPI must be initialized in each thread.

+1
source

Source: https://habr.com/ru/post/1480319/


All Articles